Microservices Idempotency

Networks fail in sneaky ways. A client sends a payment request, the server completes it, and the reply gets lost. The client tries again and risks a second charge. Idempotency solves this problem: repeating the same request produces the same result as running it once.

Layman Explanation

Pressing the elevator call button five times still brings one elevator. The extra presses change nothing. A well-built service treats duplicate requests the same way and ignores the extra presses.

Naturally Idempotent Operations

OperationIdempotent?Reason
Set status to "Shipped"YesThe final state stays the same on repeat
Delete order 501YesThe order stays deleted
Add 100 to the balanceNoEvery repeat adds again
Create a new paymentNoEvery repeat creates another payment

In HTTP, GET, PUT, and DELETE are idempotent by design. POST is not, so POST requests need extra protection.

Why Duplicates Happen

  • A client times out and retries while the first request still runs.
  • A user taps a button twice.
  • A message broker delivers a message more than once.
  • A retry policy in a gateway or service mesh replays the call.

The Idempotency Key Technique

The client generates a unique key for each business action and sends it with the request. The server remembers every key it has processed along with the stored result.

Client                              Server
  |-- POST /payments                  |
  |   Idempotency-Key: abc-123 -----> |  key unknown: process, save result
  |<---------- 201 Created ---------- |
  |   (reply lost on the network)     |
  |-- POST /payments                  |
  |   Idempotency-Key: abc-123 -----> |  key known: return saved result
  |<---------- 201 Created ---------- |  (no second charge)

Server Steps

  1. Read the key from the request header.
  2. Look up the key in a store such as a database table or cache.
  3. Return the saved response when the key exists.
  4. Process the request and save the response with the key when the key is new.

Handling Two Simultaneous Requests

Two copies of the same request can arrive at the same instant. A unique database constraint on the key lets only one insert succeed. The second request waits or receives a "request in progress" reply.

Idempotent Message Consumers

Brokers with at-least-once delivery send duplicates now and then. A consumer keeps a table of processed message ids. Before handling a message, the consumer checks the table and skips known ids.

Message arrives: id = m-77
  Is m-77 in processed_messages?
     yes --> skip and acknowledge
     no  --> do the work, store m-77, acknowledge

Run the work and the id insert inside one database transaction so a crash cannot leave them out of step.

Choosing Keys and Expiry

  • Use random identifiers such as UUIDs generated on the client.
  • Tie one key to one logical action, never to a whole session.
  • Keep keys for a limited period, such as 24 hours, to control storage.
  • Reject a reused key that arrives with different request content.

Example: Safe Money Transfer

A transfer request carries the key T-9001. The server debits the sender, credits the receiver, and stores the result under T-9001. A repeated request with the same key returns the stored confirmation. Both accounts show a single transfer, and the customer sees a calm success message and no double charge.

Key Takeaways

Idempotency makes retries safe. Use idempotency keys for create-style requests, track processed message ids in consumers, and enforce uniqueness in the database.