A product price changes in the database, but Redis still contains the old value. How would you keep cache and database consistent?
How I frame it
I'd ask: who writes price (admin CMS vs pricing engine) and where is price read (browse vs checkout). Browse can tolerate brief staleness; checkout cannot. Design different consistency per path.
Write path — keep cache in sync
- Cache-aside + invalidate on write (most common): After DB commit,
DEL product:123:priceor publishProductPriceChangedevent. All cache nodes evict; next read reloads from DB. - Write-through: Update DB then cache in same service method — simpler mental model, but cache failure must not roll back DB (log and async repair).
- Transactional outbox: Price update + invalidation message in one DB transaction — worker fans out DEL to Redis cluster. Survives crash between DB and cache.
Admin: price ₹999 → ₹799 1. UPDATE products SET price=799, version=version+1 WHERE id=123 2. COMMIT 3. Publish ProductPriceChanged(123, 799, v42) 4. All Redis nodes DEL product:123:price
Read path — never trust cache at checkout
Even with invalidation, race exists: read cache → admin updates → stale charge. At order creation / payment, re-read price from DB with row lock or compare version field. Cache is optimization for PLP; DB is authority for money.
- TTL safety net: 30–60s on price keys limits blast radius if invalidation missed.
- Version stamp in cache:
{ price, version }— checkout rejects ifversion < db_version.
Walkthrough — user in checkout during price change
User loaded cart 10 min ago (price ₹999 cached). Admin drops to ₹799. User clicks Pay. Checkout service reads DB → ₹799, creates order at current price. User sees updated total. If we had only cache, user might pay ₹999 — support nightmare and regulatory risk.
Weak answer
"Set Redis TTL to 5 seconds." TTL alone does not fix checkout race; invalidation on write + authoritative DB read at payment is required.
Follow-up questions
Invalidation message lost — how do you detect drift?
Reconciliation job compares DB prices vs Redis sample; alert on mismatch. Short TTL bounds damage.
Multi-region Redis — invalidation fan-out?
Pub/sub or Kafka invalidation topic consumed by each region's cache layer. Or use CDN/API with versioned responses.
Promotional flash price for 1 hour?
Time-bound price row in DB; cache key includes promo id + expiry. Invalidate when promo ends via scheduled job.