Design a caching strategy for an inventory system where data changes frequently. Which caching approach would you choose and why?
How I frame it
Frequently changing inventory is a poor fit for long-TTL read cache as source of truth. I split browse path (approximate OK) from purchase path (must be exact).
Recommended strategy
- Purchase path — no stale cache:
reserve()uses DB row lock or atomic Redis DECR synced to DB. Authoritative at commit time. - Browse path — short TTL + event invalidation: "In stock" badge cached 5–15s; bust cache on
StockChangedKafka event. - Approximate display: Show "Only few left" buckets (In stock / Low / Out) not exact count — reduces cache sensitivity.
- Read replicas for reporting only: Analytics on replica; never for checkout.
- Write-through for slow movers: SKUs that change once a day can cache longer with invalidation on shipment.
PLP browse: cache in_stock=true TTL 10s (stale ok) Add to cart: no stock hold yet Checkout: atomic reserve() → DB/Redis truth Why: oversell cost >> stale badge 10s
Walkthrough — flash sale SKU
iPhone launch: 500 units, 50k RPM on product page. Browse cache shows "Low stock" bucket refreshed every 10s via invalidation on each sale batch. Checkout never reads that cache — reserve() decrements authoritative counter. User who saw stale "In stock" at browse gets honest sold-out at pay — acceptable; oversell is not.
What I would avoid
Caching exact quantity=47 for 5 minutes on a flash sale SKU — guaranteed angry users at checkout and oversell incidents.
Weak answer
"Don't cache inventory at all." DB melts on browse traffic; cache with correct boundary (browse vs reserve) is required. "Cache everything with 1 hour TTL" — wrong for fast-moving SKUs.
Follow-up questions
Redis counter vs DB for flash sale?
Redis for speed; async reconcile to DB with unique reservation ids. DB is legal record for shipment.
Multi-warehouse inventory?
Cache per (sku, warehouse) or aggregate "available somewhere" for browse; reserve picks warehouse in transaction.
Link to shopping cart question?
Cart does not hold stock; cache strategy applies at browse. Reserve at checkout uses non-cached path.