Cache invalidation sequence
Client, application, cache, and database coordinating fresh data.
Cache invalidation is famously one of the hardest problems in computer science. This sequence diagram shows why it's hard and what a correct invalidation strategy looks like: reads hit the cache on success, but every write must invalidate the key so the next read fetches fresh data from the database. The diagram also shows the two paths — a cache hit that avoids a database query entirely, and a cache miss that pays the cost of the database call but still updates the cache for the next client.
Missing the invalidation step is how teams ship stale-data bugs. The client makes a write, the write succeeds, the cache still holds the old value, and the next reader gets the old data and thinks nothing is wrong. This diagram makes that risk visible and shows exactly where the DEL or INVALIDATE call belongs.
When to use this template
- Cache design reviews — sketch what data goes into the cache, when it expires, and which write paths must invalidate it before you build it.
- Incident postmortems — when stale data reaches customers, this diagram helps explain where the invalidation broke and what the fix should be.
- API documentation — show clients the ETag or cache-control headers they'll receive, so they understand when data is fresh vs stale.
How to adapt it
Extend the sequence to match your caching topology:
- Add a second cache layer (local in-process cache, then Redis) if you have one, showing validation at each level.
- Insert a publish-subscribe step after the database update, showing an event that triggers invalidation across multiple services.
- Annotate the cache TTL value on the SET message so the expiry policy is documented where developers read it.
Visual edits regenerate clean Mermaid code, so you can turn this template into your team's actual caching architecture by just editing lifelines and message labels in the editor.
Mermaid code
Copy it anywhere Mermaid is supported — GitHub, Notion, or your docs.
sequenceDiagram
actor Client
participant App
participant Cache
participant DB as Database
Client->>App: GET /user/123
App->>Cache: Check cache key user:123
alt Cache hit
Cache-->>App: Return cached value
App-->>Client: 200 OK (from cache)
else Cache miss
App->>DB: SELECT * FROM users WHERE id=123
DB-->>App: User record
App->>Cache: SET user:123 value EX 3600
Cache-->>App: OK
App-->>Client: 200 OK
end
Client->>App: PATCH /user/123 (update email)
App->>DB: UPDATE users SET email=? WHERE id=123
DB-->>App: 1 row updated
App->>Cache: DEL user:123
Cache-->>App: Key deleted
App-->>Client: 200 OK
Frequently asked questions
- What is cache invalidation and why is it hard?
- Cache invalidation means ensuring the cached copy of data is deleted or refreshed after the source changes. It's hard because a stale cache silently serves wrong data — the client gets the old value, doesn't realize it's wrong, and may take bad actions based on it. This diagram shows the two main strategies: TTL (expiry after N seconds) and active invalidation (delete when the source updates).
- Should I use TTL or active invalidation?
- Use TTL for read-heavy data that can tolerate brief staleness — user profiles, product catalogs. Use active invalidation for critical state like shopping carts or payment records, where a 10-second stale cache is unacceptable. Most production systems combine both: set a TTL as a safety net, and actively invalidate on writes so the cache stays fresh.
- What happens if my cache key gets out of sync with the database?
- Clients start seeing stale data and reporting inconsistencies. The bug is invisible until you grep your cache logs or run a consistency check against the database. This is why the invalidation step after every write is non-negotiable — forget it once and you'll find out the hard way in production.
- How do I handle cache invalidation across multiple services?
- Publish a cache-invalidation event (e.g., via Kafka or a message queue) when a write happens, so all services listening on that topic can invalidate their local caches. Alternatively, invalidate at a central cache layer (Redis) and have all services read through it. The sequence diagram method works within a single service; at scale, you need event-driven or distributed cache strategies.