Caching Strategies
Patterns for reading, writing, and invalidating cached data reliably
Overview
Caching strategies define how a cache and its backing store stay in sync on reads and writes, and how stale entries are removed. The right pattern depends on your read/write ratio, tolerance for staleness, and consistency needs. Getting invalidation and write ordering wrong is the most common source of subtle production bugs, hence the saying that cache invalidation is one of the hard problems.
Syntax / Usage
Read patterns decide who loads data on a miss; write patterns decide how the cache and database are updated together.
Cache-aside (lazy): app reads cache; on miss, app reads DB, then writes cache
Read-through: cache library loads from DB on miss transparently
Write-through: app writes cache AND DB synchronously (consistent, slower writes)
Write-back: app writes cache, DB updated async later (fast, risk of data loss)
Write-around: app writes DB only; cache filled on next read (avoids cold churn)
For writes with cache-aside, prefer to update the DB then delete the cache key (not update it), so the next read repopulates fresh data and avoids interleaving races.
Examples
A product catalog uses cache-aside with Redis: reads check Redis, misses hit Postgres and backfill with a 5-minute TTL. On update, the service writes Postgres then deletes the key.
A session store uses write-through: every session change writes to both Redis and the database synchronously, so a cache node failure never loses recent state.
A high-write metrics pipeline uses write-back: counters accumulate in memory and flush to the database every few seconds, trading durability for throughput. To fight thundering-herd on hot keys, popular entries add a small random TTL jitter and a per-key lock so only one request rebuilds a value on expiry.
Common Mistakes
- Updating the cache before the database, leaving stale data if the DB write fails
- Using write-back without accepting the risk of losing unflushed writes on a crash
- Setting identical TTLs everywhere, causing synchronized mass expiry (cache stampede)
- Caching per-user data under a shared key and leaking it across users
- Ignoring the race where a slow miss backfill overwrites a newer concurrent write
See Also
system-design-caching system-design-databases system-design-scalability