Prevent Double Spending in APIs with Idempotency Keys
If you’re building an API that involves money, inventory, or any kind of limited resource, there’s one problem you need to care about: double spend.
In this post, I’ll explain what double spend is, how it happens, and how to prevent it using idempotency keys, with a sample code at the end.
What is “Double Spend”?
Double spend happens when the same operation is accidentally executed more than once — like a user being charged twice or buying more than they should be allowed.
This is super common in real APIs. Here’s how it can happen:
A user clicks the “Buy” button twice by mistake
The client automatically retries the request due to a network timeout
A frontend bug or a slow backend causes duplicated submissions
Users spam the action before it finishes (yep, it happens)
Each of these can send two identical requests to the server — and unless you protect against it, your backend might process both.
Result? Two charges. Two orders. Double trouble.
Example:
Let’s say you have an endpoint like this:
And your user has $100 in their wallet. The client sends two identical requests by accident. Your backend processes both. Boom — the user just spent $200.
Even worse — maybe you deduct inventory or confirm a booking. You just overbooked or oversold.
Solution: Idempotency Keys
To fix this, we use something called an idempotency key.
An idempotency key is a unique identifier that the client generates and sends with the request. The server uses this key to remember if it already processed the same request.
So, even if the request is sent multiple times with the same key, the server will only process it once.
Think of it like this:
“Hey server, here’s my unique key. If you’ve seen this before, don’t do the job again — just give me the original response.”
How It Works (Step by Step)
The client generates a unique key (like a UUID).
It sends this key along with the request, usually in a header like .
The backend checks if this key already exists in a cache or database.
If the key exists → return the previous response (don’t run anything again).
If the key doesn’t exist → process the request and save the result under that key.
Sample Code (Laravel + Axios)
Backend (Laravel)
Here’s a simple middleware to handle idempotency:
Frontend (Axios Example)
Summary
Double spend bugs can be dangerous — and embarrassing. But with idempotency keys, you can make your APIs safer and smarter.
Always remember:
Generate the key on the client
Keep it constant during retries
Cache the key and response on the backend