Back to All Blogs1 min read27 Aug 2026
System Design Foundations · Part 3 of 8
Caching in Modern Applications: Speed Without Losing Correctness
“Understand cache hits, TTLs, invalidation, stampedes and where Redis fits.”
Caching in Modern Applications
Caching means storing frequently used data in a faster temporary layer so the system does not repeat expensive work for every request.
Generating diagram...
Cache Aside
async function getProduct(id: string) {
const key = `product:${id}`;
const cached = await redis.get(key);
if (cached) {
return JSON.parse(cached);
}
const product = await database.product.findUnique({
where: { id }
});
await redis.set(key, JSON.stringify(product), { EX: 300 });
return product;
}
TTL
A TTL defines how long a cached value should exist.
product:123
TTL = 300 seconds
Cache Invalidation
Update database
↓
Delete cache key
↓
Next read fetches fresh data
↓
Cache is populated again
Cache Stampede
When a very popular key expires, thousands of requests can miss at the same time and hit the database.
Possible protections include:
- request coalescing,
- distributed locks,
- TTL jitter,
- background refresh,
- stale-while-revalidate.
Note
Caching creates another copy of your data. Every additional copy creates a consistency problem that must be understood.
Redis is useful, but Redis is not automatically required for every application.
Finished this article?
Mark it done to update your series progress.