Concept Simulators / Keeping a service up

Idempotency

How retries charge twice, and how idempotency keys stop it.

On the roadmap:Intermediate · step 4: Messaging

Intermediateabout 10 to 15 min6 experiments
Experiments
New here? A few short steps show what happens, one at a time.

Settings

The server's protection

Every request that arrives is processed, so every retry is charged again.

Charged once

86.0%

Charged twice or more

14.0%

Extra charges

820

Charged, told it failed

11

701 of 5,000 customers (14.0%) were charged more than once, 820 extra charges in all. A retry that follows a lost answer cannot tell the first payment worked.

The same payments, every protection

ProtectionCharged onceCharged twice or moreExtra chargesCharged, not confirmed
4,29970182011
4,75624424411
5,0000011

How a duplicate happens

  1. Lost answer. The server charges the card, and its answer never reaches the client. The client sees nothing and retries.
  2. Slow server. The server is still working when the client gives up. The retry arrives mid-work, and a key saved only at the end is not there yet.
  3. The fix. Send the same key with every try. The server records it before it starts, and returns the first result to any repeat.

In plain words

A request is idempotent if doing it twice has the same effect as doing it once. Networks lose messages, so clients retry, and a retry of a payment that already went through would charge twice. An idempotency key lets the server recognise a repeat and give back the first result instead of doing the work again.

Why it matters

Retries are essential, and dangerous for anything that changes state. The fix is simple to describe and easy to get slightly wrong: a key saved too late still lets a duplicate through when a server is slow. Here you can see exactly which failures cause duplicates, and which protections stop them.

How real systems do it

The simulation is a simplified model. Here is what production systems add or do.

  • Stripe asks clients to send an Idempotency-Key header on POST requests. It saves the first response for the key, returns it for repeats, and may remove keys once they are at least 24 hours old.
  • By the HTTP definition, GET, PUT and DELETE are idempotent and POST is not. A PUT that sets a value is safe to repeat. A POST that appends or charges is not unless it carries a key.
  • Message queues such as Amazon SQS standard queues deliver at least once, so a consumer may see a message twice. Handlers have to be idempotent, often by recording the message's ID in the same transaction as the effect.
  • A database unique constraint on the key is a simple, strong guard: the second insert fails instead of doing the work again. Kafka's idempotent producer does something similar with sequence numbers.

Study: Idempotency

Once you have played with it, learn the same idea from people who build these systems. Watch first for the picture, then read for the detail.

Check yourself

1 of 4. A payment succeeds but its answer is lost. The client retries without a key. What happens?

Go deeper