Making POST Idempotent with Idempotency Keys
Learn how to use idempotency keys to make POST requests safe to retry, preventing duplicate resource creation and double-charged payments.
Detailed Explanation
The Problem with Non-Idempotent POST
POST is not idempotent — sending the same request twice creates two resources. This is dangerous in scenarios like:
- Payment processing (double charges)
- Order placement (duplicate orders)
- Email sending (duplicate notifications)
Idempotency Keys
An idempotency key is a unique identifier sent with a request. The server stores the key alongside the response. If the same key is sent again, the server returns the stored response instead of processing the request again.
Implementation
POST /api/payments HTTP/1.1
Content-Type: application/json
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
{
"amount": 5000,
"currency": "USD",
"customer_id": "cus_123"
}
First request: Server processes the payment, stores the result keyed by the idempotency key, returns 201 Created.
Retry (same key): Server finds the stored result, returns the same 201 Created response without processing the payment again.
Server-Side Logic
1. Receive request with Idempotency-Key header
2. Check if the key exists in storage
- If YES: Return the stored response (HTTP status + body)
- If NO: Process the request normally
3. Store the response with the key (TTL: 24-48 hours)
4. Return the response to the client
Key Generation Best Practices
| Approach | Example | Pros |
|---|---|---|
| UUID v4 | 550e8400-e29b-41d4-a716-446655440000 |
Simple, universally unique |
| Composite | user-123:order:2026-01-15T10:30:00Z |
Deterministic, debuggable |
| Hash | sha256(request_body + timestamp) |
Content-based deduplication |
APIs That Use Idempotency Keys
- Stripe — Required for payment intents
- PayPal —
PayPal-Request-Idheader - AWS —
ClientTokenparameter on many services - Google Cloud —
requestIdquery parameter
Client-Side Retry Logic
1. Generate idempotency key before first attempt
2. Send POST with the key
3. If timeout or network error: retry with the SAME key
4. If 409 Conflict: the operation was already processed
5. If 2xx: success (may be original or replayed response)
Use Case
A payment gateway processes a credit card charge via POST. The client sends the request, but the connection drops before receiving the response. The client retries with the same idempotency key. The server recognizes the key and returns the original successful response without charging the card twice.