====== Cache Invalidation Patterns in Real Production Systems ====== ===== Overview ===== Cache invalidation ensures cached data stays consistent with the database in distributed systems. In real production systems, the hardest problem is: Handling concurrency and distributed timing while keeping cache consistent with DB. Most systems use a combination of patterns, not a single approach. ===== 1. Cache-Aside (Most Common Pattern) ===== ==== Concept ==== Application manages cache manually. Cache is a read-through optimization layer, DB is the source of truth. ==== Read Flow ==== Client → Application → Cache ↓ miss Database → Cache → Response ==== Write Flow ==== Client → Application → Database update → delete cache key ==== Where it is used ==== Microservices systems E-commerce platforms Social applications ==== Pros ==== Simple Safe Easy to debug Flexible ==== Cons ==== Cache miss causes DB hit Small stale window possible ===== 2. Write-Through Cache ===== ==== Concept ==== Write goes through cache first, then DB. ==== Flow ==== Client → Cache → Database ==== Pros ==== Strong consistency No stale cache ==== Cons ==== Slower writes Higher cost ===== 3. Write-Behind Cache ===== ==== Concept ==== Write goes to cache first, DB updated asynchronously. ==== Flow ==== Client → Cache (ACK) ↓ async Database ==== Pros ==== Very fast writes High throughput ==== Cons ==== Risk of data loss Complex recovery ===== 4. TTL-Based Invalidation ===== ==== Concept ==== Cache expires automatically after time. ==== Example ==== user:123 → TTL = 5 minutes ==== Pros ==== Simple Safe fallback ==== Cons ==== Stale data until expiration ===== 5. Event-Driven Invalidation ===== ==== Concept ==== Database changes emit events to invalidate cache. ==== Flow ==== Service → Database update → Event (UserUpdated) ↓ Cache Service → delete/update cache ==== Pros ==== Decoupled systems Scalable ==== Cons ==== Eventual consistency Event delay or loss possible ===== 6. Update-on-write vs Invalidate-on-write ===== ==== 🟥 6.1 Update-on-write (RISKY under concurrency) ==== ===== Problem ===== Concurrent updates can cause race conditions between DB and cache. ===== Scenario ===== Request A updates value = "A" Request B updates value = "B" ===== Problem ===== If execution order is mixed: DB = B Cache = A ❌ ===== Conclusion ===== Update-on-write is unsafe due to: Race conditions Out-of-order execution Distributed timing issues ==== 🟩 6.2 Invalidate-on-write (SAFE pattern) ==== ===== Concept ===== Do NOT update cache. Only delete it. ===== Why it is safe ===== Only DELETE operations on cache No stale value can be written ===== Read Flow ===== Client → Redis (miss) → Database → Set cache Always consistent with DB. ===== 7. Comparison Table ===== ^ Aspect ^ Update-on-write ^ Invalidate-on-write ^ | Cache operation | SET | DELETE | | Race condition risk | ❌ High | ✅ Low | | Out-of-order updates | ❌ Dangerous | ❌ Harmless | | Cache correctness | ❌ Fragile | ✅ Reliable | | Debug complexity | High | Low | ===== 8. Key Insight ===== Cache is not the source of truth. DB = source of truth Cache = disposable optimization layer Invalidate-on-write works because: Even if cache is wrong, it will be deleted anyway. ===== 9. Production Pattern ===== Most systems use: WRITE: 1. Update Database 2. Delete Cache READ: Cache hit → return Cache miss → DB → set cache ===== 10. Why Update-on-write still exists ===== Used only in limited cases: Simple data Low concurrency Ultra-fast read-after-write requirement Examples: Session storage Feature flags Simple counters ===== 11. Bonus Topics ===== Cache stampede problem Mutex / singleflight Request coalescing Kafka-based cache invalidation Outbox pattern for reliability