Idempotency is critical in web services. It means the same request can be repeated multiple times and get the same result. A general question to identify it is: does data change if the same call is repeated?
✅ Looking up a customer's name or address from a system is usually idempotent, as there is no change in the system.
✅ Changing a customer's name to XYZ is usually idempotent because updating it multiple times to the same value has consistent results.
❌ Creating an entity with
POST is not idempotent. We want to create a user by providing their first name. If we repeat the same call multiple times, the service will consider them to be separate requests and create multiple users.
This could have bad results depending on the operation. For an e-commerce site, it could mean charging for the same purchase multiple times.
An elegant solution is to have the client pass a
tracking-id with each request and to keep it consistent between retries.
- Client calls POST with
- Server creates a checkpoint storage entity from the id (after checking if in use)
- Server performs the operation logic
- Server updates the checkpoint entity with the operation response
- Server returns the operation response
Say the network call returning the response is lost. The client sees a timeout and decides to retry the request.
- Client calls POST again with the same
- Server checks whether
tracking-idis in use and discovers the idempotent response from the first operation.
- Server returns the idempotent response to the caller.
In this way, the unique
tracking-id provided by the caller ensures that the operation provides idempotency
This is a generic multi-purpose design. The checkpoint logic can be built as middleware and used by all write operations.
However, there are a few edge cases to consider with this design.
The checkpoint entity was created with the id, but there is no operation response available yet.
Best option is to return a
409 Conflict and have the client try again.
Services can fail at any time - the machine is recycled, the process runs out of memory, or the data center hits issues.
This pattern complements the use of Service Queues to perform roll-forward or roll-back of failed operations.
Excited to hear other solutions or design others use.