Attackers continuously request product IDs that don't exist. Every request misses Redis and hits the database. How would you solve this?
How I frame it
This is cache penetration — intentional or accidental flood of invalid keys. Every miss becomes a DB query. Goal: make invalid lookups cheap at the edge without touching the database.
Defence layers
- Negative caching: Cache
product:invalid-id → NOT_FOUNDwith short TTL (1–5 min). Attackers hit Redis, not Postgres. - Bloom filter: Probabilistic set of all valid product IDs in memory. "Definitely not in catalog" → 404 without DB. Rare false positive → one DB read.
- Input validation: Reject malformed IDs at API gateway (numeric range, UUID format, max length).
- Rate limiting: Per IP / API key on
GET /products/:id— slow brute-force scans. - WAF / bot scoring: Block sequential ID scan patterns (123, 124, 125…).
GET /products/999999999 (does not exist) 1. Bloom filter: not in set → 404 (0 DB) OR 2. Redis negative cache HIT → 404 (0 DB) OR 3. DB miss once → set negative cache TTL 3min
Walkthrough — attacker scan
Attacker sends 10k random IDs/sec. Without negative cache: 10k DB queries/sec. With Bloom + negative cache: ~0 DB after warm-up. Legitimate rare typo (one invalid ID) pays one DB miss, then cached.
Trade-offs
Negative cache TTL too long: new product ID that was invalid yesterday but created today delayed visible. Keep TTL short (minutes) or invalidate Bloom on product create event.
Weak answer
"Add more DB read replicas." Attack scales with replicas; stop hits at cache/Bloom layer.
Follow-up questions
Bloom filter false positive?
Rare — one extra DB read. Tune false positive rate vs memory. Rebuild Bloom on catalog bulk import.
Attacker poisons negative cache with valid new SKU?
On product create, publish invalidation for that key and update Bloom. Negative entry must be deleted on CREATE event.