Redis: Caching & Beyond
Theme
Palette
Download
Caption (tap to copy)
📖 Deep dive (full written explanation)
This cover reframes a frustration every backend engineer eventually feels: the database is the slow part. The point it makes is that the database isn't slow because it's poorly built — it's slow precisely because it's doing the right thing. It's writing durably to disk, enforcing constraints, maintaining indexes, and guaranteeing correctness on every request. That careful work has a cost.
Post two is about stakes. Post one explained what Redis is; this post explains why you'd reach for it. The answer comes in two halves: caching, which exploits the fact that reads vastly outnumber and outpace changes, and the 'beyond' workloads — rate limiting, sessions, queues, locks — that fit Redis far better than a relational database.
The foundational observation behind all caching is that reads repeat while the underlying data changes rarely. Think about a product page, a user profile, or a feature-flag configuration: these are read thousands or millions of times between the occasional update. Serving each of those identical reads by querying the database from scratch is enormous wasted effort.
Caching exploits this asymmetry directly. You compute or fetch the answer once, store it in Redis, and serve every subsequent identical read from memory until the data actually changes. N expensive, repeated database reads collapse into one. The bigger the read-to-write ratio — and in most applications it's lopsided — the more dramatic the savings.
This bar chart visualizes the payoff of caching in terms of database load. With no cache, every single read reaches the database, so it carries essentially all the work. When a cache is cold — just started or recently cleared — it's still warming up, so the database sees a moderate load as misses populate the cache. Once the cache is warm, the database is barely touched; it only handles the small fraction of requests that miss.
The lesson is that the value of a cache compounds with its hit rate. A cache that serves ninety percent of reads cuts database load by roughly ninety percent. This is why hit rate is the metric to watch, and why a cold cache after a restart can briefly stress a database that's normally idle.
This slide translates the speed gap into something users feel. Under real load, a database query might take anywhere from fifty to two hundred milliseconds, especially if it joins tables or contends with other queries. A Redis read is reliably under a millisecond. On its own that's a big gap; the multiplier is what makes it decisive.
A single page often triggers dozens of data lookups — the user, their permissions, their cart, recommendations, config. If each of those is a slow database call, the latencies stack into a sluggish page. Move the repeated ones to Redis and the same page assembles in a fraction of the time, with no change to the database itself. Perceived performance is one of the most direct things a cache buys you.
Here the argument shifts from average performance to resilience under stress. The database is typically the most fragile component during a traffic spike because its resources are finite and expensive to scale: connection slots, locks, disk I/O. When requests surge, queries queue, connections exhaust, and the database can tip from slow into failing.
A warm cache acts as a shock absorber. During a spike, the flood of requests is served from Redis memory, and only the small stream of cache misses reaches the database. Instead of seeing ten times its normal load, the database sees a trickle. This shielding effect is often the difference between gracefully handling a viral moment and a full outage.
This pipeline diagram traces the shielding effect step by step. A spike arrives — say ten times normal traffic. It hits Redis first, which serves the overwhelming majority as cache hits straight from memory. Only the misses, a small trickle, flow through to the database, which therefore stays healthy and responsive throughout the surge.
Reading it as a pipeline makes the leverage obvious: the cache is positioned exactly where it can intercept load before it reaches the fragile component. The database never experiences the spike at full strength. This is why teams that run read-heavy services treat a warm cache not as an optimization but as a core part of staying available.
This slide introduces the 'beyond' half of the value proposition. Some workloads are genuinely awkward in a relational database and elegant in Redis. Counting events per second means hammering a row with updates and fighting lock contention in SQL; in Redis it's a single atomic INCR. Deduplication means expensive DISTINCT queries or unique constraints; in Redis it's a set with O(1) membership.
Expiring sessions automatically requires cron jobs or cleanup queries in SQL; Redis does it natively with TTLs. Ranking requires sorting large result sets repeatedly; a Redis sorted set keeps things ranked continuously. Passing messages between services means polling a table; Redis offers pub/sub and streams. None of this is caching — it's using Redis as the right data structure for the job.
This snippet shows rate limiting, a perfect example of a 'beyond' workload, implemented in essentially three commands. INCR atomically increments a per-user counter and returns the new value — no read-modify-write race even when many requests arrive at once. EXPIRE sets a sixty-second TTL so the counter resets each minute; it only takes effect meaningfully on the first hit of the window.
The application logic is then trivial: if the returned count exceeds the limit, reject the request. There's no table to create, no rows to lock, no cleanup job to delete old counters — the TTL handles expiry automatically, and each check costs microseconds. Implementing the same fixed-window rate limiter in a relational database would be far more code and far slower under load.
This comparison sets the two worlds side by side. With Redis: repeated reads return in sub-millisecond time, the database is shielded during load, sessions and queues and rate limits are easy, and you can run on a smaller, cheaper database because it handles less traffic. Without it: every read hits disk, the database melts under spikes, the 'beyond' features become awkward bolt-on hacks in SQL, and you end up paying for an oversized database to brute-force the load.
Framed this way, Redis is a cost and reliability lever, not just a speed trick. The same workload can be cheaper to run and far more resilient simply because the read traffic and the awkward workloads are handled by the tool built for them.
This slide confronts a common organizational mistake: treating caching as a 'we'll add it later' optimization. The reasoning sounds prudent — don't add complexity before you need it. But the read patterns that make caching valuable exist from the very first day; they simply hurt more as traffic grows. Deferring the cache doesn't avoid complexity, it relocates it into an overworked, oversized database and the operational pain of scaling it.
The practical stance is to design with the cache in mind early, even if you tune it later. Know which reads are hot and repeatable, structure your keys, and have the invalidation story figured out. Retrofitting caching into a system that assumed the database would always be the answer is much harder than building it in from the start.
This recap compresses the stakes into five lines: reads repeat far more than writes; a cache turns N reads into one; sub-millisecond beats fifty-to-two-hundred milliseconds; Redis shields the database during spikes; and it handles jobs relational databases are bad at. Each is a concrete reason Redis appears in so many production stacks.
The through-line is that Redis is about both performance and resilience, and that its value spans pure caching and a set of workloads that simply fit it better. Understanding why these things matter is what motivates learning the mechanics in the next post.
Post two made the case for caring. Post three opens the hood: the single-threaded event loop that runs your commands, how Redis persists to disk so it can survive a restart, how key expiration and TTLs actually work, how it evicts data when memory fills, and how replication keeps it available.