Intermediate14 min

Idempotency

Make an operation safe to repeat, so retries and duplicates don't cause damage.

By the end of this lesson, design idempotent operations and use idempotency keys to dedupe retries.

How deep?
How the pieces actually move.

An operation is idempotent if doing it twice has the same effect as doing it once. SET balance = 100 is idempotent; ADD 100 to balance is not. Because networks guarantee at-least-once delivery (retries, duplicate messages, ambiguous timeouts), idempotency is what makes distributed systems safe.

First, the whole system

First, see the whole system. Then we’ll open it up.

Idempotency key dedupe

Idempotency key dedupe

  1. A client sends an idempotency key; the service checks a key store: if new, process once and save the result; if seen, return the saved result without re-processing.
flowchart LR
  client[Client] -->|request + idempotency-key| svc[Service]
  svc -->|key seen?| store[(Key store)]
  store -->|new| do[Process once, save result]
  store -->|seen| replay[Return saved result]

For naturally non-idempotent actions (charge a card, send an email), the client supplies an idempotency key; the server records the key with the result, so a retry with the same key returns the original result instead of acting again. This turns unreliable at-least-once delivery into effectively-once behavior — the practical replacement for the myth of exactly-once.

Abstraction leak

This is where the abstraction starts leaking.

'Exactly-once delivery' doesn't exist over an unreliable network — the ack can always be lost. What you actually build is at-least-once delivery plus idempotent processing. Chasing exactly-once at the transport layer is chasing a ghost.

Duplicate side effects

Trigger
A non-idempotent operation is retried or a message is redelivered.
Symptom
Double charges, duplicate records, repeated emails.
Blast radius
Data integrity and user trust.
Mitigation
Idempotency keys, dedupe stores, idempotent operation design.

Deep dive: Partial Failure

How does an idempotency key make 'charge $100' safe to retry?

The server stores the key with the charge result; a retry with the same key returns that stored result instead of charging again.

Idempotency makes retries safe within one service. What pattern makes a write and its event atomic across systems?

Next: Transactional Outbox →