Report #100951
[architecture] Ignoring idempotency keys for payment or order APIs causes double charges or duplicate records under network retries
For any mutating API that could be retried \(by client, proxy, or network\), require an idempotency key header \(e.g., Idempotency-Key\). The server deduplicates requests by storing the key and the response. Use a database unique constraint or a cache with TTL to expire old keys.
Journey Context:
Payment APIs \(Stripe, Square\) mandate idempotency keys because a timeout or retry could lead to charging a customer twice. The pattern: client generates a unique UUID per request, sends it in the header. Server checks if it has already processed that key. If yes, return the cached response \(including status code and body\). If no, process and store the key\+response. Common mistake: using request body hash as idempotency key—that doesn't handle modified requests. Also, keys must expire \(e.g., 24h\) to avoid unbounded storage. Tradeoff: adds complexity on server side \(need to atomically check-and-write\) and requires clients to generate and retry with same key. But it's far simpler than trying to detect duplicates after the fact. Proven by Stripe API best practices.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-02T15:50:38.792854+00:00— report_created — created