What Is It?
Idempotency is one of the most important ideas in software that almost nobody talks about outside engineering.
The clean definition is:
an operation is idempotent if doing it multiple times has the same effect as doing it once
That sounds abstract until you see where it matters.
If a payment request times out and your system retries it, did the customer get charged once or twice? If a webhook arrives again, does your app create a duplicate order? If a background job crashes halfway through and restarts, does it corrupt state?
Modern systems fail, networks drop packets, users double-click buttons, servers retry automatically, and distributed workflows replay messages all the time.
So the real question is not:
“How do we make sure this only runs once?”
The real question is:
“How do we make repeated execution safe?”
That is idempotency.
Why Does It Matter?
- Retries are everywhere. Networks are unreliable, so robust systems retry by default.
- Exactly-once execution is usually a fantasy. Most real systems approximate reliability through at-least-once delivery plus idempotent handling.
- Money and state changes make duplicates expensive. Payments, orders, emails, shipments, and provisioning flows all break badly when repeated actions are not safe.
- It is a deep systems habit, not just an API trick. Once you see it, you notice it in databases, queues, event processing, and recovery design.
How It Actually Works
Suppose a client sends a request to create a charge.
The server processes it, but the response gets lost before the client receives confirmation.
Now the client has a problem:
- maybe the charge happened
- maybe it did not
- the safest move is often to retry
But retrying blindly is dangerous unless the server can recognize:
this is the same intended operation as before
That is where idempotency keys come in.
The client attaches a stable unique key to the request, like:
idempotency_key = order_8472_charge_attempt_1
The server stores the result associated with that key.
If the same request arrives again with the same key, the server does not perform the side effect again. It returns the already-recorded result.
So instead of:
- request 1 -> charge happens
- request 2 -> charge happens again
You get:
- request 1 -> charge happens, result stored
- request 2 -> same key detected, original result reused
That is the core pattern.
Where This Shows Up
Payments
This is the classic case. If a payment provider or merchant system does not handle retries idempotently, duplicate charges become inevitable under failure.
Webhooks
Webhook senders often retry deliveries. Your receiver must treat duplicate delivery as normal, not exceptional.
Job queues
Background workers crash, restart, and replay jobs. If the handler is not idempotent, recovery creates corruption.
Resource provisioning
Creating users, subscriptions, invoices, or cloud resources needs duplicate protection if upstream systems retry.
Distributed event processing
Many event-driven systems promise at-least-once delivery, not exactly-once delivery. The application layer has to absorb duplicates safely.
Idempotency vs “Nothing Happens Twice”
This is where people get confused.
Idempotency does not mean the operation literally executes only once at the machine level.
It means repeated executions do not create repeated effects.
That distinction matters.
A handler may run twice. A message may be delivered three times. A user may click submit four times.
If the system is well designed, the outcome still converges to one intended effect.
That is why idempotency is really about effect semantics, not raw execution count.
HTTP Helps, But Only Partly
HTTP methods hint at this idea:
GETshould be idempotentPUTis intended to be idempotentDELETEis usually treated as idempotentPOSTis often not idempotent by default
But this is only surface-level.
A POST /charges endpoint can still be made idempotent with a key.
A PUT endpoint can still be badly implemented and non-idempotent in practice.
So idempotency is not just about verb choice. It is about system behavior under repetition.
What People Get Wrong
1. “Retries are dangerous, so avoid retries”
Wrong lesson. Retries are necessary. Unsafe retries are the problem.
2. “The database transaction solves this”
Transactions help local atomicity. They do not automatically solve duplicate intent across retries, networks, and external side effects.
3. “Exactly once” is a default property
Usually it is not. Most systems achieve practical reliability through replay tolerance.
4. “Idempotency is only for payments”
Payments make the pain obvious, but the principle is much broader.
Practical Design Pattern
A strong mental model is:
separate the identity of the intended action from the accidental number of delivery attempts
Then build the system around that identity.
That usually means:
- generate a stable operation key
- persist it near the side effect
- check whether it has already been applied
- reuse prior result if yes
- apply exactly one durable state transition if no
This is one of the quiet foundations of robust software.
Reliable systems are not the ones that never get hit twice. They are the ones that stay correct when they do.
Best Resources to Learn More
- Stripe engineering writing on idempotency.
- Amazon and distributed-systems material on retries and at-least-once delivery.
- Kleppmann on messaging, fault tolerance, and exactly-once myths.
- Good systems design discussions around duplicate suppression and workflow recovery.