Double-Charged, Double-Booked, Double-Sorry: The Case for Idempotency
Why your API doesn't know it already said yes (And how to fix that).
It’s late at night. You’re bleary-eyed, buying concert tickets on your phone. You tap Purchase. The spinner spins. And spins. And spins.
The Wi-Fi bar is doing that thing where it’s one bar but also somehow zero bars. You tap again. Then once more for good measure. The app finally loads — and shows you three confirmation emails.
You now own six tickets to a Tuesday night jazz show you didn’t even want to attend twice.
Congratulations. You’ve just been betrayed by a system that had no idea it already said “yes.”
The Mindset Shift: Expect Chaos, Design for It
Most developers think about the happy path: request goes in, response comes out, everyone claps.
But distributed systems don’t care about your feelings. Networks drop packets. Servers restart mid-request. Load balancers time out. Mobile clients retry because 3G happened.
The right mindset isn’t “this will work” — it’s “this will be called more than once, and I need the second call to not make things worse.”
That’s idempotency: an operation you can safely repeat without changing the outcome beyond the first execution.
Like pressing an elevator button. Pressing it seventeen times doesn’t make the elevator arrive seventeen times. The first press registered. The rest are just you processing anxiety.
Where This Bites You?
1. Payments and Bookings
The classic. A user clicks Pay Now. The response gets lost. The client retries.
Without protection, the payment processor charges twice.
With idempotency, the second request returns the same receipt as the first.
Stripe, PayPal, and every serious payment API you’ve ever used handle this with an Idempotency-Key header — a unique ID per intent, supplied by the client. Same key? Same result. New key? New charge.
2. Order Fulfillment
An e-commerce warehouse system receives an order. The HTTP response times out before delivery. The order service retries.
Without idempotency, the customer receives two blenders and a surprisingly awkward returns conversation.
With idempotency, the warehouse sees the same order ID, shrugs, and sends the single confirmation it already sent.
3. Email and Notifications
A notification service crashes after sending a welcome email but before marking it as sent in the database. On restart, it scans for unsent emails and… sends the welcome email again. And again.
New users open their inbox to seventeen near-identical “Welcome to our platform!” messages and immediately assume they’ve been hacked.
4. Infrastructure Provisioning
You run terraform apply. It times out. You run it again.
An idempotent provisioner checks what already exists and skips it.
A non-idempotent one creates a second load balancer with a slightly different name, charges you for both, and leaves one doing absolutely nothing for six months until someone notices a confusing bill.
How Does Idempotency Works?
The most common pattern is the idempotency key + server-side record:
The server stores a record: “key abc-123 → result: order confirmed, ID: 7829.” Any future request with the same key gets that stored result back immediately.
The underlying operation — charging the card, placing the order, sending the email — runs exactly once.
The TTL Question: Why You Can’t Keep Records Forever?
Here’s where it gets interesting.




