Define how much staleness your application can tolerate before choosing an invalidation strategy. Measure the acceptable staleness window and use it to guide whether you need TTLs, active invalidation, or a hybrid approach.
- TTL (time to live): let cached items expire automatically.
- Active invalidation: explicitly remove or update cache entries on database writes.
TTL (time to live)
TTL means writing items into the cache with an expiry time. Example: set a user bio in Redis with a 60-second TTL. When the TTL expires, Redis evicts the entry; the next request misses the cache, fetches the latest data from the database, and repopulates the cache. TTL is a lazy approach: it trades eventual consistency for simplicity and scalability. It’s a good fit when short periods of staleness are acceptable (e.g., follower counts, trending metrics). But if your application cannot tolerate even a second of stale data (e.g., privacy settings), TTL alone is insufficient.
Cache stampede (thundering herd)
A common TTL-related failure mode is the cache stampede: when a very popular cache key expires, many clients request it simultaneously, causing a surge of identical DB queries. This can overload your database.
- Add jitter to TTLs so hot keys don’t all expire at the same instant.
- Request coalescing / single-flight: ensure only one in-flight DB fetch repopulates the cache for a given key.
- Per-key mutexes or locks to serialize refreshes.
- Background refresh (prefetching) for known hot keys.
- Serve a slightly stale value while refreshing asynchronously (stale-while-revalidate).

Active invalidation
Active invalidation means the application updates or deletes the cached copy as part of the write flow. Typical pattern: write the new value to the DB, then delete or update the corresponding cache entry so future reads fetch fresh data. This approach minimizes the staleness window and is required when correctness is critical. However, active invalidation can be tricky because of races. For example, a read may occur between the DB write and the cache delete, potentially repopulating the cache with the old value. Common strategies to make active invalidation safer:- Double-delete: delete the cache before and after writing to the DB (or delete after DB write and repeat shortly after).
- Write-through / write-behind: write the value to the cache as part of the DB update so the cache holds the new value immediately.
- Versioned keys or optimistic concurrency: include a version or timestamp in cache keys/values so readers can detect stale entries.
- Distributed locks or single-flight: serialize cache refreshes to avoid races.
If you invalidate the cache in the wrong order relative to the DB write, you risk serving stale entries. Design your write+invalidate ordering carefully and consider extra safeguards (double-delete, versioning, or locking) to guarantee correctness.

Choosing the right approach
There’s no single answer — choose based on your correctness requirements, traffic patterns, and operational complexity:- Use short TTLs (with jitter) for high-throughput, eventually-consistent data (home feed, counts).
- Use active invalidation for security- or privacy-sensitive fields (permissions, feature flags).
- Use longer TTLs for rarely-changing data (user profile information) to reduce read latency and DB load.
- Combine strategies: TTLs + jitter for general load reduction, request coalescing to avoid stampedes, and active invalidation for critical fields.

Industry defaults (good starting points)
These are tunable defaults — measure your latency, cache hit rate, and correctness requirements and iterate.
