====== 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