Decision guide
Where to Store Idempotency Keys
Database, Redis or both — where should idempotency records live?
Side by side
| Criterion | Same database as the business data | Redis only | Hybrid (Redis lock + DB record) |
|---|---|---|---|
| Atomic with business write | Yes | No | Yes (DB is source of truth) |
| Latency | DB round trip | Sub-millisecond | Fast path, DB on commit |
| Expiry | Cleanup job / partitions | Native TTL | TTL + cleanup |
| Failure risk | Contention on hot rows | Lost keys on failover → duplicates | More moving parts |
| Operational cost | Low | Low | Medium |
When to choose each
Same database as the business data
Key, fingerprint, status and response stored in the same transaction as the write.
Choose when
- Payments, orders, anything financial
- You need atomicity between dedupe and effect
Avoid when
- Extremely high-throughput, low-value requests
Redis only
SET NX with TTL for claims; response cached.
Choose when
- Low-stakes dedupe (notifications, analytics)
- Very high request rates
Avoid when
- Correctness-critical operations (not transactional with DB)
Hybrid (Redis lock + DB record)
Redis for fast in-progress locks and replay cache; DB record committed with the work.
Choose when
- High-traffic critical APIs
- Hot keys hammered by retries
Avoid when
- Small teams that don't need the complexity
Verdict
For anything involving money or irreversible side effects, keep the idempotency record in the same database transaction as the work. Add Redis only as an optimization, never as the sole source of truth.
Learn more
- Idempotency & Retry-Safe Systems
- API Design
- Databases & Transactions
- Support Idempotency-Key headers in FastAPI (FastAPI)
- Make a PHP payment endpoint idempotent (PHP)
- Make POST endpoints idempotent in Spring Boot (Spring Boot)