- rtshkmr's digital garden/
- References/
- Architecture Design Basics/
- Pattern Taxonomy/
- Fundamental Concepts/
- Idempotency/
Idempotency
Table of Contents
π΄ P0 — critical for payment systems, Stripe’s public API design is built on this
Problem #
In distributed systems, messages can be delivered more than once. Network retries, client timeouts, queue redelivery — all produce duplicates. Without idempotency, a retried payment request charges the customer twice.
Mechanism #
An operation is idempotent if applying it multiple times produces the same result as applying it once.
Naturally idempotent: GET /user/123 β same result every time
PUT /user/123 {name: "R"} β overwrites to same state
DELETE /user/123 β deleted stays deleted
NOT naturally idempotent: POST /charges {amount: 50} β creates a NEW charge each time
counter++ β increments every callMaking non-idempotent operations safe #
The standard mechanism is an idempotency key: a client-generated unique identifier attached to the request.
Client β POST /v1/charges
Idempotency-Key: "abc-123"
{amount: 5000, currency: "usd"}
Server:
1. Check: have I seen key "abc-123" before?
2. If yes β return the stored result (don't re-execute)
3. If no β execute, store result keyed by "abc-123", return resultSee also: Idempotency Keys for implementation details.
Key Trade-offs #
| Dimension | Trade-off |
|---|---|
| Storage | Must store key β result mappings; need TTL / eviction policy |
| Atomicity | Check-and-execute must be atomic (else race conditions on retries) |
| Key generation | Client-generated (Stripe model) vs server-generated (less flexible) |
| Scope | Per-endpoint? Per-resource? Global? Wider scope = more storage |
Instinct #
Every mutating API endpoint in a distributed system should be idempotent. The question is never whether but how. For payments specifically, idempotency isn’t a nice-to-have — it’s a correctness requirement.
References #
- Stripe API Docs: Idempotent Requests
- Implementing Stripe-like Idempotency Keys in Postgres β Brandur Leach (ex-Stripe)
- IETF Draft: Idempotency-Key HTTP Header
DDIA 2e Reference #
- Chapter 8: Exactly-once semantics, duplicate suppression
- Chapter 11: Stream processing and deduplication
- Chapter 12: End-to-end argument for duplicate suppression