Idempotency
An operation is idempotent when it has the same effect if it runs twice or once. A check against a store of seen IDs takes about 0.3 ms. That small cost turns each repeated delivery into no extra effect.
See it on the board
The same traffic runs on two boards. The simulator measured both when this page was built.
| Measure | Goal | Each repeated batch adds to the counts | Store of seen click IDs before the counts |
|---|---|---|---|
| Duplicates | none | 60 Fail | 0 Pass |
| Lost writes | none | 0 Pass | 0 Pass |
| Completion time | under 150 s | 103.32 s Pass | 103.32 s Pass |
| Monthly cost | 20 USD/mo | 28 USD/mo | |
| p99 latency | 8.5 ms | 8.5 ms | |
| Error rate | 0% | 0% |
Key numbers
| Number | Value |
|---|---|
| Look up one ID in a key-value store, median | 0.3 ms |
| Lookups per second, one key-value store | 30,000 ops/s |
| Time before a queue sends a job again | 30 s |
| Price of one key-value store | 4 USD/mo |
13 deliveries · 10 payments applied · 0 charged twice
How it works
Repeats are normal in distributed systems. A client retries after a timeout, a queue delivers a job again after a lost ack, and a user clicks a button twice. If each repeat charges a card or adds to a count, the result is wrong.
Some operations are idempotent by nature. To set a field to a value gives the same result each time. To add to a total or to send money does not. To make such an operation safe, give each request a stable ID, such as an idempotency key or an event ID. Before the work, the service looks for the ID in a store of seen IDs. If the ID is new, it does the work and records the ID. If the ID is known, it returns the saved result and does nothing more.
The check and the effect must be atomic. If the service records the ID but stops before the effect, the work is lost. If it does the effect but stops before it records the ID, the work runs twice. Keep both in one transaction, or use a conditional write.
The store of seen IDs grows with each request. Keep each ID only as long as a repeat can arrive, for example a few days.
In the levels you add a store of seen IDs so that each repeated delivery counts once.