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.
Application manages cache manually. Cache is a read-through optimization layer, DB is the source of truth.
Client → Application → Cache ↓ miss Database → Cache → Response
Client → Application → Database update → delete cache key
Microservices systems E-commerce platforms Social applications
Simple Safe Easy to debug Flexible
Cache miss causes DB hit Small stale window possible
Write goes through cache first, then DB.
Client → Cache → Database
Strong consistency No stale cache
Slower writes Higher cost
Write goes to cache first, DB updated asynchronously.
Client → Cache (ACK) ↓ async Database
Very fast writes High throughput
Risk of data loss Complex recovery
Cache expires automatically after time.
user:123 → TTL = 5 minutes
Simple Safe fallback
Stale data until expiration
Database changes emit events to invalidate cache.
Service → Database update → Event (UserUpdated) ↓ Cache Service → delete/update cache
Decoupled systems Scalable
Eventual consistency Event delay or loss possible
Concurrent updates can cause race conditions between DB and cache.
Request A updates value = “A” Request B updates value = “B”
If execution order is mixed:
DB = B Cache = A ❌
Update-on-write is unsafe due to:
Race conditions Out-of-order execution Distributed timing issues
Do NOT update cache. Only delete it.
Only DELETE operations on cache No stale value can be written
Client → Redis (miss) → Database → Set cache
Always consistent with DB.
| 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 |
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.
Most systems use:
WRITE: 1. Update Database 2. Delete Cache READ: Cache hit → return Cache miss → DB → set cache
Used only in limited cases:
Simple data Low concurrency Ultra-fast read-after-write requirement
Examples:
Session storage Feature flags Simple counters
Cache stampede problem Mutex / singleflight Request coalescing Kafka-based cache invalidation Outbox pattern for reliability