Tag every side-effecting request with a unique key, persist the outcome, and return the stored result on replays. Stops duplicate charges, duplicate tickets, and duplicate emails dead.
Rendering diagram…
Use idempotency keys any time a caller might retry a request that has side effects:
Distributed systems retry. Networks are flaky. Clients crash mid-request and try again. Without idempotency you get duplicates, and customers notice duplicates immediately.
The caller attaches a unique key (a UUID, a client-generated ID, or a natural business key like order-id) to each request. The server stores the (key, response) pair in a durable store when the request completes. A subsequent request with the same key returns the stored response instead of processing again.
The key is usually sent in a header (Idempotency-Key is the de-facto standard). Stripe, Shopify, and most serious APIs use exactly this.
Idempotency is not the same as deduplication. Dedup silently drops duplicates. Idempotency returns the same successful response to every duplicate so the client gets what it expected.
24 hours is a common default. 7 days is safer for billing flows where disputes surface late. Forever is usually wrong — the table grows without bound.
When a key arrives, try to insert (key, status=processing) with a uniqueness constraint. If the insert fails, another request with the same key is already running — return 409 Conflict or wait.
Not just the outcome flag. The status code, headers, and body so a retry gets a byte-for-byte match. Anything less and clients will break on "looks the same but isn't".
If a client retries while the original is still processing, what do you return? Three valid choices: 409, block until done, or return a 202 "still processing". Document your choice and stick to it.
Every log line and every metric dimension should include the idempotency key. When a duplicate incident hits, you'll know immediately whether it's a retry or a genuinely new request.
request-123 from one tenant shouldn't collide with another's.Accept file uploads (CSV, Excel), validate every row against business rules, report errors to the submitter, and import clean data into the target system. The essential pattern for bulk data intake.
Take a basic record and enhance it with data from external APIs — geocoding addresses, resolving company info, validating phone numbers, scoring leads. Transform minimal input into rich, actionable data.