Redis Caching Patterns

Caching is the most common reason teams adopt Redis. Putting frequently read data in memory, in front of a slower database or API, can turn 50 ms queries into sub-millisecond lookups and absorb traffic that would otherwise overwhelm your primary store. But a cache adds a second copy of your data, and with it every hard problem in caching: staleness, invalidation, thundering herds, and memory limits.

This page covers the standard patterns for reading and writing through Redis, how to choose TTLs and eviction policies, and how to avoid the failure modes that turn a cache into an outage amplifier.

TL;DR

Quick Example

Cache-aside in Python with TTL jitter and invalidation on update:

The next read after an update misses and reloads fresh data from the database.

Core Concepts

Read Patterns

Write Patterns

For most applications, cache-aside plus invalidate-on-write is the right default.

TTL Strategy

TTLs bound staleness and let unused data age out:

Eviction Policies

When Redis reaches maxmemory, the maxmemory-policy decides what to remove:

A dedicated cache instance with allkeys-lfu or allkeys-lru is simpler and safer than mixing cache and durable data on one instance.

Cache Stampedes

When a hot key expires, hundreds of concurrent requests miss at once, all hit the database, and all try to rebuild the same value. This is the thundering herd or dog-pile effect. Defenses:

Consistency Pitfalls

Caches are eventually consistent by nature. Common races:

For strong cross-system consistency, drive invalidation from the database's change stream using change data capture.

Best Practices

Treat the Cache as Disposable

Your application must work, more slowly, with an empty or unavailable cache. Wrap Redis calls with timeouts and fall back to the source of truth on errors, so a cache outage doesn't become a full outage.

Cache at the Right Granularity

Cache the expensive thing: a rendered fragment, an aggregated query result, or an external API response. Caching tiny rows individually can create more round trips than it saves.

Monitor Hit Rate and Memory

Track keyspace_hits/keyspace_misses, evictions, memory use, and latency. A falling hit rate or rising evictions means keys, TTLs, or memory need attention.

Consider Client-Side Caching for Very Hot Keys

Redis supports server-assisted client-side caching (CLIENT TRACKING): clients keep a local copy and Redis notifies them on change. It removes network round trips entirely for extremely hot keys.

Common Mistakes

Caching Without a TTL

Keys with no expiry accumulate forever, and one missed invalidation serves stale data indefinitely. Every cache write should set an expiry.

Caching Errors and Empty Results Carelessly

Caching "not found" (negative caching) protects the DB from repeated lookups for missing items, but use a short TTL. Never cache transient errors like timeouts as if they were real results.

Putting Sessions or Queues on an Evicting Cache

If the instance uses allkeys-lru, it may evict session data or queued jobs under memory pressure. Keep durable data on a separate instance with noeviction and persistence enabled; see Redis persistence.

FAQ

Should I update or delete the cache on writes?

Delete. Updating the cache from the write path creates ordering races between concurrent writers and can leave an older value cached. Deleting forces the next reader to load the latest committed data. Combine it with a TTL as a safety net.

What TTL should I use?

As long as the business can tolerate stale data, and no longer. Start with minutes for most entity caches, seconds for fast-changing values, and add jitter. Measure hit rates and adjust; very short TTLs on cold data mostly add misses.

Redis or an in-process cache?

In-process caches (a local LRU map) are faster, with no network hop, but each instance holds its own copy and invalidation across instances is hard. Redis provides one shared cache for all instances. Many systems use both: a tiny short-TTL local cache in front of Redis.

How do I cache in a Redis Cluster?

The same patterns apply. Keys spread across shards by hash slot. Keep multi-key operations (MGET, transactions) on keys that share a slot by using hash tags like {user:42}:profile. See Redis Cluster.

Related Topics

References