Idempotency
0-day streakReview

Your progress

Level 1

0 XP100 XP to level 2
0day streak
0best streak
0topics started
0cards reviewed
    Review cards

    Progress is stored only in this browser. No account is required.

    Idempotency: the 60-second story

    Idempotency

    You tapped Pay, it failed, you tapped again. Why two debits?

    The first debit committed; only the reply was lost. A timeout isn’t a failure. It’s missing information.

    From the phone, these look identical

    1. Never arrived: a retry is safe
    2. Failed halfway: it depends what committed
    3. Committed, reply lost: a retry repeats it

    Idempotent means the same response?

    Bad: Same response

    DELETE answers 204, then 404. Both are fine.

    Good: Same effect

    Doing it n times leaves the state of doing it once.

    Climb only as high as the write needs

    Set instead of increment. Check a version. Let the client pick the ID. For payments, an idempotency key with the stored result.

    Claim the key and save the reply in one transaction

    A unique index on (account, key) lets one attempt win. The payment and its stored response commit together, so a retry replays the answer.

    A client wrapper mints a fresh key per attempt. Safe?

    The bug

    No. Each retry becomes a new payment. Mint the key on the first tap, save it on the device, and reuse it.

    Every hop dedupes its own retries

    Each service derives downstream keys from the key it received, its caller and the step. A retried checkout recreates the same keys, so every hop spots the duplicate.

    Where it shows up

    1. Payments: idempotency keys at the API
    2. Order creation: client-chosen IDs
    3. Ledgers: version-checked updates
    4. Consumers: an inbox of seen message IDs

    Say it like this

    A timeout doesn’t say whether we committed. Make updates naturally idempotent; for payments, the client sends a key once per operation, and we store it with the result in one transaction.