Academy · Messaging & Async

Idempotency & exactly-once

Networks retry. The same "charge card" message can arrive twice. Now you've double-charged.

Open the interactive version → diagrams, practice & more

The problem

Networks retry. The same "charge card" message can arrive twice. Now you've double-charged.

The idea

Make operations idempotent: applying them twice has the same effect as once.

How it works

Make operations idempotent so applying them twice equals once. The client attaches an idempotency key; the server atomically records "key → result" and on a duplicate returns the stored result instead of redoing the work. *Exactly-once delivery is impossible over an unreliable network, so the real recipe is at-least-once delivery + idempotent processing = exactly-once effect*. Enforce it where it's atomic — a unique constraint or INSERT … ON CONFLICT — not a check-then-act two concurrent retries can both pass.

The tradeoff

You must store and check keys with a retention window long enough to outlive retries but bounded so it doesn't grow forever. The transactional-outbox pattern closes the sibling gap (DB write commits but the event publish fails) by writing the event in the same transaction and relaying it later. The cost is bookkeeping; the payoff is the only safe way to handle the retries that will happen.

In the wild

Stripe's API uses an Idempotency-Key header for exactly this reason.

Interview deep dive

Flow

  1. Client generates an idempotency key per logical operation.
  2. Server atomically records key → result (unique constraint).
  3. A duplicate key returns the stored result, skipping the work.
  4. Expire keys after a window that safely outlives retries.

Watch for

Interviewer trap

Say exactly-once effect = at-least-once delivery + idempotent apply, enforced atomically.

Related Academy

Part of Academy on SystemLore — system design interview prep with 148 deep topics, interactive diagrams, and a practice game. Practice this one →