What are Idempotency Keys in APIs?
Learn what idempotency keys are, how they make API retries safe, and how to implement them for payments and other mutations.
Expected Interview Answer
An idempotency key is a unique client-generated identifier attached to a mutating API request (like POST /payments) so that if the same request is retried after a timeout or network failure, the server can recognize the duplicate and return the original result instead of performing the operation again.
Networks are unreliable: a client can send a request, the server can process it successfully, and the response can be lost before the client sees it — the client then cannot tell whether the operation actually happened, so a naive retry risks double-charging a card or double-creating a resource. With idempotency keys, the client generates a unique key (typically a UUID) per logical operation and sends it in a header on every attempt of that operation, including retries. The server stores the key along with the result of the first successful execution, and on any subsequent request carrying the same key, it looks up the stored result and returns it directly without re-running the underlying business logic. This turns an inherently non-idempotent operation like “charge a card” into one that is safe to retry, which is essential for reliable client-side retry logic and for services fronted by unreliable networks or timeouts.
- Makes retries of non-idempotent operations (payments, order creation) safe from duplication
- Lets clients retry aggressively on timeout without fear of double side effects
- Gives a clear, auditable record of exactly which logical operation each request represents
- Decouples “did my request succeed” from “was my request received,” which a lost response otherwise conflates
AI Mentor Explanation
An idempotency key is like a unique token stamped on an appeal slip a fielding captain hands the umpire — if the same slip is handed over twice because the first hand-off got lost in the confusion, the umpire recognizes the token and gives the same ruling again instead of re-running the review from scratch. Without that token, a second appeal might trigger a second, possibly different review process and confuse the scoreboard. The umpire’s log of tokens already ruled on is exactly what a server’s idempotency key store does. This lets the fielding side safely resend an appeal if they are unsure it was received.
Step-by-Step Explanation
Step 1
Client generates a unique key
Before the first attempt of a logical operation, the client creates a UUID (or similar) as its idempotency key.
Step 2
Client sends the key with every attempt
The same key is attached (usually as an Idempotency-Key header) on the original request and any retries.
Step 3
Server checks for an existing record
On receiving a request, the server looks up whether that key has already been processed.
Step 4
Return stored result or process and store
If the key exists, return the stored result without re-executing side effects; otherwise process normally and store the result under that key.
What Interviewer Expects
- Explains the core problem: a lost response makes retries ambiguous for non-idempotent operations
- Describes the client generating and sending the key on every retry, and the server storing the result
- Mentions real-world usage, e.g. Stripe’s Idempotency-Key header for payments
- Considers key expiration/storage and what happens on concurrent requests with the same key
Common Mistakes
- Confusing idempotency keys with naturally idempotent HTTP methods like GET or PUT
- Not storing the actual response, only a flag, so a retry cannot return the original result
- Ignoring what should happen if two requests with the same key arrive concurrently
- Forgetting that the key must be client-generated per logical operation, not server-generated
Best Answer (HR Friendly)
“An idempotency key is a unique ID the client attaches to a request like a payment, so if the client has to retry because it never got a response, the server recognizes it already handled that exact request and just returns the original result instead of doing it again. This prevents things like accidentally charging a customer twice when a network call times out.”
Code Example
app.post("/payments", async (req, res) => {
const idempotencyKey = req.headers["idempotency-key"]
if (!idempotencyKey) {
return res.status(400).json({ error: "Idempotency-Key header required" })
}
const existing = await idempotencyStore.get(idempotencyKey)
if (existing) {
return res.status(existing.statusCode).json(existing.body) // safe replay
}
const result = await chargeCard(req.body)
const responseBody = { paymentId: result.id, status: result.status }
await idempotencyStore.save(idempotencyKey, {
statusCode: 200,
body: responseBody,
expiresAt: Date.now() + 24 * 60 * 60 * 1000,
})
res.status(200).json(responseBody)
})Follow-up Questions
- What should the server do if two requests with the same idempotency key arrive at nearly the same time?
- How long should an idempotency key’s stored result be retained, and why?
- How is an idempotency key different from making an HTTP method like PUT idempotent by design?
- How would you scope idempotency keys per client to prevent one client from colliding with another’s key?
MCQ Practice
1. What core problem does an idempotency key solve?
Idempotency keys let the server recognize a retried request and return the original result instead of re-executing side effects.
2. What must the server store when handling a request with an idempotency key?
The server must store the response so a retry with the same key can return that exact original result.
3. Who is responsible for generating the idempotency key?
The client must generate the key up front so the exact same key can be resent on every retry of that logical operation.
Flash Cards
What is an idempotency key? — A client-generated unique ID attached to a request so retries return the original result instead of repeating side effects.
Why are they needed? — Because a lost response makes it ambiguous whether a non-idempotent operation actually succeeded.
What does the server store? — The actual result of the first execution, keyed by the idempotency key, to return on retries.
Real-world example? — Stripe requires an Idempotency-Key header on payment creation requests.