May 27 2025
Idempotency in APIs
What idempotency is, why it matters in distributed systems, and how to implement it so unstable networks do not corrupt data.
Andrews Ribeiro
Founder & Engineer
4 min Intermediate Systems
Track
System Design Interviews - From Basics to Advanced
Step 13 / 19
The problem
Networks fail. Clients retry. Timeouts happen. Messages reappear.
That sounds like an edge case until the day it becomes an incident.
If a user tries to pay $100, gets no response, and clicks again, what does your system do?
If the answer is “charge twice,” that is not an operational detail. It is a serious bug.
Mental model
In plain language, idempotency means this:
perform the same operation more than once and still end up in the same final state
The focus is on the final effect, not on how many times the code ran.
Easy example:
DELETE /users/123is usually idempotent. After the first call, repeating it still leaves the user deleted.
Non-idempotent example:
POST /chargescreates a new charge every time it is repeated.
In distributed systems, idempotency matters because repetition is not rare. It is normal environmental behavior.
Breaking it down
Which HTTP methods are idempotent and why
In HTTP semantics, GET, PUT, and DELETE are usually treated as idempotent.
POST usually is not, because it often means “create something new.”
But interviews rarely stop at the formal definition.
What really matters is:
- can this operation arrive again?
- if it does, does the result still need to be just one thing?
Idempotency key: the standard pattern
The most common way to make a critical POST safe is with an idempotency key.
Simple flow:
- the client sends the request with a unique key
- the server stores that key together with the result
- if the same key arrives again, the server returns the same result instead of creating everything a second time
That works very well for:
- payments
- order creation
- expensive operations that cannot be duplicated
How to implement it: Redis vs database
Redis usually shows up when you want fast lookup and a simple TTL.
A database makes sense when the main record itself can carry the guarantee, or when durability matters more.
The exact design depends on the case, but the central idea does not change:
- identify the repeated operation
- bind it to a key
- return the previous result instead of processing again
The senior detail here is deciding what that key actually represents. It needs to point to the same business intent, not just to “two requests that look similar.” If the same key can mean different operations, you traded duplication for incorrect behavior.
Idempotency in queue consumers
Repeated delivery in a queue brings this topic back outside HTTP.
If the consumer receives the same order_paid message twice, it cannot:
- create two orders
- issue two refunds
- decrement inventory twice
The mechanism may differ, but the question is the same:
how do I recognize that this was already processed?
TTL and expiration of idempotency keys
The key does not need to live forever in every case.
It needs to live long enough to cover the real retry window.
If the operation may be retried minutes or hours later, the TTL has to reflect that. If it expires too early, a late retry may become duplication. If it lives forever with no reason, you accumulate cost and unnecessary operational noise.
You also need to decide what to do when the first attempt is still in progress. In some flows, the second call should later receive the same result. In others, it makes sense to answer with something like “still processing.” The important part is that the behavior is predictable.
Simple example
Imagine a payment endpoint.
The client sends:
- amount
- payment method
idempotency_key
The server receives it and checks whether that key already exists:
- if it does not exist, it processes the payment, stores the result, and replies
- if it already exists, it returns the same previous result
Now, if the client times out after the first processing and retries, the second call does not charge again.
That is the real value of idempotency: turning unavoidable repetition into safe behavior.
Common mistakes
- Thinking retry is too rare to care about.
- Trusting only the client not to repeat.
- Using idempotency only in HTTP and forgetting the queue consumer.
- Expiring the key too early.
- Confusing “do not repeat the call” with “support repetition safely if it happens.”
How a senior thinks
People with more experience usually treat repetition as a fact of the environment, not as bad luck.
The reasoning usually sounds like this:
If the same intent arrives twice, I need a clear way to recognize it and prevent duplicate side effects.
That helps because it puts the right question in the center. It is not “will it repeat?” It is “what happens when it repeats?”
That also improves API design. Instead of only discussing endpoint and payload, you start discussing operational guarantees.
What the interviewer wants to see
In interviews, idempotency shows operational maturity very quickly.
The interviewer wants to see whether you:
- understand why timeout and retry make repetition unavoidable
- can explain the role of the idempotency key
- connect HTTP and queues to the same underlying problem
- think about key validity window and storage durability
Idempotency does not make the network more reliable. It makes your system less fragile when the network behaves like a network.
Quick summary
What to keep in your head
- Idempotency means repeating the same operation still reaches the same final state.
- Retry without idempotency becomes duplicate charge bugs, duplicated orders, and repeated side effects.
- An idempotency key is the most common pattern for making a critical POST safe under repetition.
- The same reasoning applies to queue consumers that may receive the same message again.
Practice checklist
Use this when you answer
- Can I explain idempotency with a payment example?
- Can I say why timeouts and retries make this unavoidable?
- Can I suggest an implementation with a key and stored result?
- Can I apply the same idea to a queue consumer?
You finished this article
Part of the track: System Design Interviews - From Basics to Advanced (13/19)
Next step
API scenarios at scale Next step →Share this page
Copy the link manually from the field below.