RizTech Academy logo
RizTech Academy
Key-Value Stores and CachingLesson 1 of 630 min

Why a cache, and what it costs you

Almost every real web application has two databases. The first is the one you have spent this whole course on — PostgreSQL, the source of truth. The second is a cache, and it is usually Redis. This module is that second database, and the reason nearly nobody teaches it is the reason you should learn it: it is where a startlingly large fraction of production performance work actually happens.

What a cache is

A cache is a fast, temporary copy of data that is expensive to produce, kept close to where it is needed. You compute something once — a query result, a rendered page, an API response — store it, and serve the stored copy to the next thousand requests instead of computing it again.

without cache:   request → PostgreSQL (12ms) → response      × 10,000 = 120 seconds of DB work
with cache:      request → Redis (0.2ms)     → response      × 10,000 = 2 seconds, DB untouched

That is the whole pitch. Redis holds data in memory, so a read is tens to hundreds of microseconds — often 50–100× faster than the same query against PostgreSQL, which has to plan, touch pages, and possibly go to disk. For data that is read far more than it changes, that gap is enormous and free money.

Why "just in memory" is most of the magic

PostgreSQL is fast, and it caches pages in shared_buffers too. So why is Redis so much quicker?

  • No query planning. GET book:42 is a hash lookup, not a parsed, planned, optimised query.
  • No relational machinery. No joins, no MVCC visibility checks, no transaction isolation on the read path.
  • Purpose-built data structures in RAM. A Redis hash is a hash table; a sorted set is a skip list. The operation is the data structure's native operation.
  • Single-threaded, no lock contention on the common path. Redis runs commands one at a time, extremely fast, with none of the coordination a multi-user relational database needs.

The cost of all that speed is the point of the module: Redis gives up almost everything PostgreSQL guarantees. It is not a smaller database — it is a different kind of thing.

What you give up, stated up front

Because this is the half that causes the bugs:

  • It is not durable by default. Redis is memory-first. Configured casually, a restart or crash can lose recent data — sometimes all of it. The last lesson of this module is entirely about this, because treating a cache as a database is the classic disaster.
  • It has no schema, no relationships, no joins, no foreign keys. It is a key pointing at a value. Any structure across keys is your problem.
  • It is limited by RAM. Memory is far more expensive than disk, so a cache holds a working subset, not everything. When it fills, it evicts — another lesson of its own.
  • A cached copy can be stale. The moment you copy data, the copy can disagree with the source. Keeping them in step ("cache invalidation") is famously one of the two hard problems in computing, and it is a whole lesson here.

The mental model: PostgreSQL is the source of truth; Redis is a fast, disposable, possibly-stale copy of the hot parts. If Redis vanished, your application should get slower, not wrong.

When a cache genuinely helps

Not everything should be cached. A cache earns its place when:

Reads vastly outnumber writes. A book's details are read on every page view and change once a year. Ideal. A live bank balance changing every second is not.

The computation is expensive. A dashboard aggregating millions of rows; a query with several joins; an external API call that is slow or rate-limited or costs money per call.

Slight staleness is acceptable. A product's review count being a few seconds out of date harms nobody. Its price, or its stock level at checkout, is a different matter — and the judgement of which is exactly the engineering.

The same result serves many requests. A cache of per-user data that is never read twice buys nothing; a cache of the homepage every visitor sees is pure win.

When it does not — and the honest warning

A cache is not a fix for a slow query. This is the mistake that matters most, and it is worth stating bluedly: if a query is slow because it lacks an index, add the index (module 7). A cache in front of an unindexed query hides the problem until the cache misses — on a cold start, after a deploy, during a traffic spike — and then every miss hammers the slow query at once, often taking the database down exactly when you are busiest. Fix the database first; cache second.

Other cases where a cache is the wrong tool: data read once, data that must always be current, and data where the cost of serving a stale value is high. And every cache adds a moving part — a second system to run, monitor and reason about — so it is a cost, not only a benefit.

The costs you take on

Adding a cache is a real engineering decision with a real bill:

  • A second system to deploy, monitor, secure and keep available.
  • Invalidation logic — the hard part — so the copy does not drift from the truth.
  • A new class of bug: the cache and the database disagreeing, which is maddening to debug because the code looks right and the data is wrong.
  • A cold-start problem: an empty cache after a restart means every request misses at once.
  • Reasoning about consistency: your app now has two sources that can differ, and you must know which wins and when.

None of this is a reason to avoid caching. It is a reason to cache deliberately — the theme of the whole module.

Why Redis specifically

Redis is the default cache for good reasons: it is fast, battle-tested, and — the thing that sets it apart — it has real data structures. Most caches store opaque blobs. Redis stores strings, hashes, lists, sets and sorted sets, with atomic operations on each, which lets it do things a plain cache cannot: leaderboards, rate limiters, queues, real-time counters. That is the next lesson, and it is why Redis is used for far more than caching.

Alternatives exist — Memcached is a simpler pure cache (no data structures, no persistence), and every cloud has a managed Redis (ElastiCache, MemoryStore, Azure Cache). Redis is the one to learn because its concepts transfer everywhere.

Check your work

What a cache is. A fast, temporary copy of expensive-to-produce data, kept close to where it is needed.

Why Redis is so much faster than PostgreSQL. In-memory, no query planning, no relational machinery, native data structures, single-threaded with no lock contention — often 50–100× on a read.

The mental model. PostgreSQL is the source of truth; Redis is a fast, disposable, possibly-stale copy of the hot parts.

The property that copy has. If Redis vanished, the app should get slower, not wrong.

Four things you give up. Durability by default, schema/relationships/joins, unlimited size (RAM-bound), and guaranteed freshness.

Four conditions that justify a cache. Reads far outnumber writes, expensive computation, tolerable staleness, and the same result serving many requests.

The most important thing a cache is not. A fix for a slow query — add the index first, or a cold cache stampedes the slow query and takes the database down.

Five costs of adding a cache. A second system, invalidation logic, cache-versus-DB bugs, cold starts, and consistency reasoning.

What sets Redis apart from a plain cache. Real data structures with atomic operations — which enable leaderboards, rate limiters and queues.

Redis versus Memcached. Memcached is a simpler pure cache; Redis adds data structures and persistence.

Practice

  1. Time the same lookup against PostgreSQL and against a value in Redis. Compute the ratio.
  2. List five pieces of data in an application you know. For each, decide whether it should be cached, and say why.
  3. Find one that changes often and is read rarely. Explain why caching it is pointless or harmful.
  4. Take a slow query. Cache its result, then reason through what happens on a cold start under load. Then add the missing index instead and compare.
  5. Write down, for a cache you would add, what happens to the application if Redis disappears. Confirm the answer is "slower, not wrong".
  6. Describe the invalidation problem for one cached value: when must it be refreshed or removed?
  7. Estimate how much RAM caching your busiest 10,000 objects would take, and compare with your database size.
  8. List the moving parts you take on by adding a cache, and decide whether the read pattern justifies them.

Official documentation

Next: the data structures that make Redis more than a cache.

Stuck on this lesson?

Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.

About the internship