Problem
Retries, at-least-once brokers and network timeouts cause the same request to arrive more than once. Without protection, duplicates create double charges, duplicate orders or repeated side effects.
Also known as: idempotency-key, deduplication-receiver
Make a consumer or API safely handle duplicate requests or messages so repeated delivery has the effect of one.
Retries, at-least-once brokers and network timeouts cause the same request to arrive more than once. Without protection, duplicates create double charges, duplicate orders or repeated side effects.
An idempotent receiver ensures that processing the same request twice has the same outcome as processing it once. It is the standard defence against the duplicates that retries and at-least-once delivery inevitably produce.
The client generates a unique key per logical operation and reuses it on every retry. The server records the key with the outcome.
POST /payments
Idempotency-Key: 7f3a-91c2
BEGIN;
INSERT INTO idempotency(key, request_hash) VALUES ('7f3a-91c2', 'h1')
-- unique constraint; conflict means duplicate
perform charge, store response
COMMIT;
If the insert conflicts, the server loads the stored response and returns it. If the key exists with a different request hash, it returns 422. For message consumers, the key is the message id, and the dedup record is written in the same database transaction as the state change, so a crash cannot separate them.
Low - one table or cache
Medium - retention and cleanup jobs
Medium - atomicity subtleties
Race lets two concurrent duplicates both execute
Key expires before a late retry arrives
Key stored without the effect, or the effect without the key, after a crash