Idempotent Focused Architecting

Idempotent Focused Architecting is an approach to software engineering that handles multiple exactly-similar calls to a system and can be used as a forcing function to help you build better software.

Photo by Brett Jordan

The Opinionated TLDR

Greatly favor idempotent solutions for RESTful APIs, GraphQL, messaging systems, etc. If idempotence is not an option then document in detail why not. Try not to choose frameworks that are unable to support idempotence.

Introduction

Software engineers have a lot of tools, frameworks, and abstractions to choose from, and that choice further limits how a problem is solved. Selecting a specific abstraction becomes a forcing function to drive how to design, test, code, CI/CD, and finally release software.

A robust and hardened GraphQL, RESTful API, or messaging system requires idempotence across the entire API. We can also apply idempotence to our software development processes such as testing and CI/CD.

Idempotence in Design

A system is idempotent when multiple exactly similar calls to a system have the same effect as a single call.

Examples are:

  • Trying to create the same user multiple times results in a single user.
  • Processing the same message multiple times results in the same outcome.
  • Deleting a user multiple times results in only one user deletion.

Advantages

Provided is a non-exhaustive list of advantages to applying Idempotent Focused Architecting.

Less Logic

In a system that is not idempotent, there will often be a need to verify if an action has already occurred. For example, we may need to check if a user does not exist before calling a RESTful API to delete the user (so we can return a 404): something that may not be necessary if the API is idempotent.

Easier To Test

Less logic means there are fewer code paths to test.

Focused Design Decisions

A developer has fewer choices in an implementation, leading to more consistent APIs internally and throughout the industry.

For example, DELETING a resource will always behave the same: it would return a 200 (OK) status with a message body containing the number of deleted items.

To quote:

.. 200 (OK) status code if the action has been enacted and the response message includes a representation describing the status — rfc7321 Section-4.3.5

In the wild, I’ve seen developers return a 404 while others would return a 500. I’ve seen drawn-out conversations on stopping the duplicate creation of resources, etc.

A Solution to Some Problems

In some cases, it simply isn’t possible to find a solution to a problem without taking an Idempotent approach. For example, it is impossible to assure that a resource is created only once without any candidate keys or a primary key [1].

Another example. In most RESTful API solutions, a primary key is generated and returned at resource creation time. Making that same RESTful API call a second will result in a new resource and primary key: a duplicate user or invoice!

A possible idempotent solution would be to have a primary key available before resource creation: passed at invocation.

Robust and Reliable

An idempotent system is less likely to have unintended side effects. Idempotent Focused Architecting forces the developer to consider edge cases that may not be apparent with other approaches. For example, you’re more likely to write tests that attempt to delete or add a user twice.

Another example. Deleting multiple resources, say all comments for a given article, would not be idempotent. The first call would delete all existing article comments, but a second call may also delete new comments posted the exact moment after the delete. Applying Idempotent Focused Architecting, we have to find a solution. One such solution would be to provide a time (or time range) of article comments to delete.

Another solution would be to “design the problem away” by assuming a user deleting multiple resources, say all existing article comments, expects those resources to delete.

In both cases, the developer must think out a solution to assure idempotence in their design.

Denial of Service Attacks

Note that an idempotent system will handle spamming of actions but is not a way to handle DOS attacks.

Potentially Inefficient Inserts

Though not an idempotent solution, when adding a new resource to a server, the server can generate a sortable identifier (UUID v1 or sequence) for the resource enabling faster inserts. However, this solution is not viable if the API needs to create non-guessable resource ids.

An idempotent solution would need to generate a resource id ahead of time: passing that id as part of the call to create the resource, making it less likely that inserts are in sorted order. However, as noted above, in this solution, we could generate non-guessable IDs if those are required.

Goes Beyond APIs

Idempotent Focused Architecting goes beyond just APIs. For software development processes, we may want to have the ability to:

  • run tests multiple times or at the same time
  • run SQL migration script numerous times against the same database
  • etc

In this case, developers are less likely to make mistakes during the development process.

Conclusion

A system is idempotent when multiple exactly similar calls to a system have the same effect as a single call. Idempotent Focused Architecting is an abstraction a software architect can apply to their designs, enabling more robust software solutions.

Advantages to an idempotent system are less logic, more straightforward tests, more focused design decisions, more robust and reliable APIs, and improved software development processes.

[1] I would not recommend using, and thus exposing, an identifier that is user-editable or may contain personally identifiable information (PII). An email makes for a great UUID but not a very good URI.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Eric Hosick

Eric Hosick

74 Followers

Creator, entrepreneur, software architect, software engineer, lecturer, and technologist.