Caching is one of the highest-leverage performance tools available, and one of the easiest to get subtly wrong. The classic joke — "there are only two hard things in computer science: cache invalidation and naming things" — exists because stale cached data causes bugs that are genuinely difficult to track down.
What Redis is actually good for
Redis is an in-memory data store, which makes it fast for exactly the operations that benefit from avoiding a database round trip: caching expensive query results, storing session state, rate limiting counters, and as a message broker for background job queues. It's not a replacement for your primary database — it's a fast layer in front of or alongside it.
Core caching patterns
Cache-aside (lazy loading)
The application checks the cache first; on a miss, it queries the database, then writes the result to the cache for next time. This is the most common pattern because it's simple and only caches data that's actually being requested — but it means the first request after a cache miss is always slow, and a cache failure falls back cleanly to the database.
Write-through
Every write goes to the cache and the database together, keeping them in sync. This avoids stale reads but adds latency to every write and means you're caching data whether or not it's ever read again.
Write-behind
Writes go to the cache immediately and are flushed to the database asynchronously. This is fast but introduces a window where data exists in the cache but not yet durably in the database — a real risk if the cache fails before the flush completes.
Cache invalidation strategies
| Strategy | How it works | Trade-off |
|---|---|---|
| TTL expiration | Cached data automatically expires after a set time | Simple, but data can be stale for up to the full TTL window |
| Explicit invalidation | Application actively deletes/updates the cache key when underlying data changes | More accurate, but requires finding every code path that changes the data |
| Versioned keys | Cache key includes a version identifier that changes when data updates | Avoids explicit deletion, but old versions linger until TTL cleanup |
In practice, most production systems combine TTL as a safety net with explicit invalidation for the specific paths where staleness would cause real problems.
What to cache, and what not to
Good caching candidates: expensive aggregate queries, data that changes infrequently relative to how often it's read, and computed results that are costly to regenerate. Poor candidates: data that changes on nearly every read, or data where staleness has a real business cost (like available inventory at checkout) unless invalidation is handled very carefully.
Common mistakes
- Caching without a clear invalidation plan. If you can't answer "what happens when this data changes," you've built a system that will eventually serve stale data with no obvious cause.
- No monitoring on cache hit rate. A cache with a low hit rate is adding complexity and a network hop without delivering the performance benefit it's there for.
- Treating Redis as durable storage. Even with persistence enabled, Redis should hold data you can afford to lose or regenerate — not the sole copy of anything critical.
- Unbounded key growth. Caches without TTLs or eviction policies grow indefinitely and eventually cause memory pressure that affects the whole instance.
Recommended approach
Start with cache-aside and TTL expiration — it's the simplest pattern to reason about and covers most use cases well. Move to explicit invalidation only for the specific data paths where staleness genuinely matters. Monitor hit rate and memory usage from day one, not after a performance incident.
Conclusion
Redis makes a real performance difference, but the pattern you choose matters more than the fact that you're caching at all. The wrong pattern trades a performance problem for a correctness problem — and correctness problems are almost always more expensive to debug.
Kiaanlab designs caching and task queue infrastructure as part of cloud architecture engagements, with invalidation strategy considered from the start. Tell us where your application is slow and we'll help you find out if caching is actually the fix.