Home / System Design / Concepts / Idempotency Concepts
CONCEPT SHEET · Concepts
Idempotency
One-liner: An operation is idempotent if doing it N times has the same effect as once; it is what makes retries and at-least-once delivery safe.
Article Concepts © Arthur Bernier Jr 531 words 1 code block
Say this#
SAY THIS
Idempotent — f(f(x)) = f(x); SET x=5 yes, x += 1 no.
Idempotency key — client-generated unique ID per logical operation (Idempotency-Key header; Stripe popularized it).
At-least-once delivery — broker/retries may duplicate; the default in most queues.
At-most-once — fire and forget; may lose.
Exactly-once processing — at-least-once delivery + idempotent/deduplicating consumer; the achievable version.
Dedupe table / seen-set — store processed IDs with TTL (Redis SETNX, unique index in DB).
Natural idempotency — upserts, PUT with full state, conditional writes (IF version = n).
Conditional write / compare-and-set — optimistic concurrency: UPDATE ... WHERE version = 3.
Retry with exponential backoff and jitter — the client side of the contract.
Retry storm — synchronized retries amplify an outage; jitter and budgets prevent it.
Safe vs idempotent HTTP methods — GET/HEAD safe; GET/PUT/DELETE idempotent; POST/PATCH not by default.
How it works#
TEXT Copy
client --POST /payments, Idempotency-Key: 7f3a--> server server: lookup key in Redis/DB hit, in-progress -> 409 or wait hit, done -> return stored response (same status/body) miss -> INSERT key (unique) ; do the work ; store response ; return
Client generates a UUID per intent (same key on retries of the same action; new key for a new action).
Server atomically claims the key (INSERT ... ON CONFLICT DO NOTHING or SETNX key value EX 86400).
Executes the side effect once; persists result keyed by the idempotency key (ideally in the same transaction).
Replays return the stored result. Keys expire after 24 h (Stripe) or a reasonable window.
Consumer-side (queues): processed_events(event_id PK) inserted in the same DB transaction as the business write; duplicate event → unique violation → ack and skip.
Trade-offs#
Choice Pro Con Idempotency keys Safe client retries, exactly-once semantics for POST Storage for keys/responses; key scoping (per user) Dedupe in Redis Fast, TTL built in Not transactional with the business write; risk if Redis loses data Dedupe in DB (unique index) Atomic with the write DB load; table growth needs TTL/partition pruning Natural idempotency (upsert, CAS) No extra state Not every operation can be expressed this way Broker "exactly-once" (Kafka transactions) Handles Kafka→Kafka pipelines Doesn't cover external side effects (email, payment)
Numbers#
Stripe idempotency keys are honored for 24 hours.
Dedupe window should exceed the maximum retry horizon (broker redelivery + client backoff), typically hours to a day.
SQS FIFO dedupe window: 5 minutes based on MessageDeduplicationId.
In the interview#
SAY THIS
Say it unprompted at every POST and every queue consumer: "Clients send an idempotency key; the server dedupes so retries are safe."
Say: "Delivery is at-least-once, so consumers are idempotent: insert event_id into a processed table in the same transaction as the write."
Follow-up: "Where do you store the key?" → "Redis with TTL for speed, or a DB unique index when it must be atomic with the write; I'd pick the DB for payments."
Follow-up: "Can you get exactly-once?" → "Not in delivery; in effect , yes, via idempotent consumers or transactional outbox + dedupe."
Creator
Written by Arthur Bernier Jr (Big Poppa Code). Arthur Bernier Jr — Big Poppa Code — is a software engineer, educator and entrepreneur: a former CTO at VC-backed startups and engineering lead at a billion-dollar company, mentor to 800+ engineers, now Senior Director of AI, Computer Programming and Cloud Computing at Per Scholas, and the host of the Deeper Than Code podcast. Everything on this page is his original teaching material.
bigpoppacode.io
License © Arthur Bernier Jr all rights reserved