03
Idempotency keys — the industry pattern
Client generates a unique key (UUID) and sends it in a header: Idempotency-Key: abc123. Server stores: {key → response}.
- First request with key
abc123 → process normally, store the response, return it.
- Retry with same key → server sees the key exists, returns the stored response without re-processing.
- Key TTL: usually 24 hours — long enough to cover any reasonable retry window.
Stripe pioneered this in their public API. Clients send a key; the second retry returns the same charge. Most payment APIs and many non-payment APIs (GitHub Apps, Twilio) now support the pattern.
Idempotency-key enforcement (Postgres)
-- client sends Idempotency-Key header
-- server upserts into an idempotent-requests table:
CREATE TABLE idempotency_keys (
key TEXT PRIMARY KEY,
user_id BIGINT NOT NULL,
request_hash TEXT NOT NULL, -- SHA-256 of body
response JSONB,
status_code INT,
created_at TIMESTAMPTZ DEFAULT now(),
expires_at TIMESTAMPTZ NOT NULL -- e.g. now() + INTERVAL '24 hours'
);
-- On request:
-- 1. SELECT existing row FOR UPDATE
-- 2. If hit + request_hash matches → return stored response (200)
-- 3. If hit + request_hash differs → 409 Conflict
-- 4. If miss → INSERT placeholder, execute, UPDATE with response
Idempotency-Key FlowMermaid
sequenceDiagram
participant C as Client
participant S as Server
participant DB as DB
C->>S: POST /charge
Idempotency-Key: abc123
S->>DB: check idem_keys
DB-->>S: not found
S->>DB: INSERT charge, INSERT idem_key(abc123, response)
S-->>C: 200 OK
Note over C: Network error · retry
C->>S: POST /charge
Idempotency-Key: abc123
S->>DB: check idem_keys
DB-->>S: found · response stored
S-->>C: 200 OK (same response)