How to implement the cache-aside pattern with Redis
Implement cache-aside with Redis: design namespaced keys, read-through on miss, set TTLs and an LRU eviction policy, invalidate keys on write, and guard against stampedes with TTL jitter.
What and why
The cache-aside pattern stores expensive query results in Redis so repeated reads skip the database. The application controls the cache: it reads from Redis, falls back to the database on a miss, and writes the result back. This is the most common caching strategy because it is simple and resilient to cache outages.
Prerequisites
- A Redis instance reachable from your application.
- A primary datastore such as PostgreSQL.
- A Redis client for your language.
Steps
1. Start Redis
docker run -d --name redis -p 6379:6379 redis:7
2. Design cache keys
Use stable, namespaced keys that encode the query:
user:profile:42
product:list:category=books:page=1
Namespaces make targeted invalidation possible.
3. Implement read-through
On read, try Redis first; on a miss, load from the database and populate the cache:
def get_user(user_id):
key = f"user:profile:{user_id}"
cached = redis.get(key)
if cached:
return json.loads(cached)
user = db.fetch_user(user_id)
redis.set(key, json.dumps(user), ex=300)
return user
4. Set TTL and eviction
Always set a TTL (ex=300 above) so stale data expires. Configure a maxmemory policy such as allkeys-lru so Redis evicts cleanly under pressure:
redis-cli CONFIG SET maxmemory-policy allkeys-lru
5. Invalidate on write
When the underlying data changes, delete the key so the next read repopulates it:
def update_user(user_id, data):
db.update_user(user_id, data)
redis.delete(f"user:profile:{user_id}")
Deleting is safer than updating the cache directly, which can race with concurrent writes.
6. Prevent cache stampedes
When a hot key expires, many requests may hit the database at once. Mitigate with a short lock or a randomized TTL jitter so keys do not all expire together:
ttl = 300 + random.randint(0, 60)
Verification
Call the read path twice and confirm the second call hits Redis (use MONITOR or client metrics). Update the record and confirm the next read returns fresh data. Under load, database query counts should drop sharply.
Next Steps
Add metrics for hit ratio, consider write-through or write-behind for write-heavy data, and use Redis cluster or a managed Redis for high availability.
Prerequisites
- A running Redis instance
- An application with a primary datastore
- Basic key value knowledge
Steps
- 1Start Redis
- 2Design cache keys
- 3Implement read-through
- 4Set TTL and eviction
- 5Invalidate on write
- 6Prevent cache stampedes