Skip to content

System Design

Idempotency Keys

O(1) time per request to check whether a key was already handled · O(n) space to remember n distinct keys. Real systems expire old keys after a while, so this doesn't grow forever.

The idea, in plain English

You've probably clicked a 'Pay Now' button twice because the page seemed frozen. Then you worried you had just been charged twice. An idempotency key fixes that. It's a unique ticket number the app attaches to that one purchase attempt. The server keeps a log of ticket numbers it has already handled. Say the same ticket number shows up again, because the click — or a network retry — got sent twice. The server doesn't charge you again. It just hands back the same result as last time, as if it never ran the action twice.

How it works

  1. 1Before sending a request that changes something, like 'charge this card,' the client generates one unique key for that attempt. It attaches the key to the request.
  2. 2The server checks a lookup table: has this exact key been seen before? If yes, skip the action. Just return the result saved from the first time.
  3. 3If the key is new, perform the action for real. Save the key and its result together. Then return the result.

When you'd use it

Use idempotency keys once your app is popular enough that flaky networks, slow pages, or retry logic start sending the same request more than once. Payments, placing an order, and sending a signup email are exactly the kind of action you never want to run twice by accident.

Common beginner mistakes

  • Generating a brand-new key every time you retry, instead of reusing the same key for the same attempt. That defeats the whole point — the server can no longer tell it's a repeat.
  • Remembering only that 'this key was used,' without saving the actual result. Then a retry can't get back the original answer it needs, like the order ID.

Try it — edit and run

Click the code to edit · press ⌘/Ctrl+↵ to run

Editable code. Tab and Shift+Tab indent. Press Escape, then Tab, to move focus out of the editor.

Expected output — hit Run to try it
key=req-abc amount=50 repeated=no -> charged $50, charge #1
key=req-xyz amount=20 repeated=no -> charged $20, charge #2
key=req-abc amount=50 repeated=yes -> charged $50, charge #1
Total real charges made: 2

Not sure this is the right topic? See the learning paths → or where this leads →