Caching with Redis
Serve hot data from memory to cut latency and shield your database
GET and SET - it is deciding what to cache, for how long, and when to throw it away.
- implement the cache-aside (lazy-loading) pattern correctly in Express;
- choose a sensible TTL and explain what expiry does and does not guarantee;
- store sessions in Redis and know why that beats in-process memory;
- invalidate on writes and avoid the classic stale-data and stampede pitfalls;
- reason about the trade-offs: consistency, memory, and the two hard problems of caching.
1. Why cache at all?
Every request that hits your database or an upstream API pays a cost: a round trip, query planning, disk or network latency, and contention with every other request doing the same. If a hundred users load the same product page, you run the same expensive query a hundred times to produce identical bytes. A cache computes the answer once, stores it in RAM, and hands out the copy until it is no longer trustworthy.
Analogy. Think of a busy kitchen. The database is the walk-in freezer at the back: huge, authoritative, but slow to reach. The cache is the small prep station beside the stove holding the ingredients you are using right now. You do not walk to the freezer for every order - you keep a working set within arm's reach and only restock when you run out. Redis is that prep station: fast, close, and deliberately small.
Two numbers make the case. A primary-key SQL read might take 5-40 ms once you count the network and the connection pool; a Redis GET over the same network is typically 0.2-1 ms. More importantly, the cache absorbs load: the database sees a trickle of misses instead of a flood, so it stays healthy under traffic spikes.
The caveat up front: a cache is a second copy of the truth, and second copies drift. Everything hard about caching flows from that one fact. As the saying goes, there are only two hard things in computer science: cache invalidation and naming things.