# Don't compute what you can remember

Express course on caching. 20 concepts — cache hit and miss, hit ratio, CDN, Redis, TTL, cache invalidation, cache-aside, write-through, LRU, cache stampede and more — each with its English name, a diagram, an example, and a card. From the browser and CDN to in-memory stores and the CPU. At the end: a one-page cheat sheet of every concept.

- **Author:** Fedor Chishchin
- **Level:** intro
- **Reading time:** ~30 minute read
- **Published:** 2026-06-13
- **Source:** https://fedorthinks.com/learn/caching-express

---

## 1. What a cache is

A cache is one simple idea: keep a copy of an answer somewhere fast, so you don't pay to produce it twice. Get this and every cache you'll ever meet is the same trick in a different place.

### The map: 20 concepts in seven groups

> A metro map: first you see the whole set of lines, then you ride station by station.

First come three **basics** — what a cache is, hit and miss, and why it works at all. Then six groups, one per chapter: cache **layers**, the **hit ratio**, **freshness**, **strategies** for updating and evicting, the **traps**, and how to **use it well**.

Every concept that follows has the same shape: its **English name** (learn it — it's the term), a picture from everyday life, a **diagram**, and a **card** with the fields _problem_, _idea_, _example_, _cost_, _when to use_, and _related_.

_Diagram: The basics on top, then six groups — chapters 2–7 follow them._

### Cache — a cache remembers the answer

> A notepad on your desk next to a slow filing cabinet — once you've looked something up, you jot it down, so next time you read the note instead of crossing the room again.

A **cache** is a small, fast store that holds the result of expensive work — a database query, a computed page, a downloaded file — so the next request for it is cheap. The expensive thing happens once; the cheap read happens many times. That's the entire principle. Everything else is detail about where the notepad lives and when to trust what's on it.

_Diagram: The app asks the cache first. It only goes to the slow source when the answer is missing._

#### Cache (the notepad by the cabinet)

- **Problem:** The same expensive work gets done again and again.
- **Idea:** Store the result somewhere fast and read it from there.
- **Example:** A computed page, a database query result, a downloaded file — kept in the cache.
- **Cost:** Memory for the copies, and the risk that a copy goes stale.
- **Related:** The rest of the course is about where caches live and when to trust them.

### Cache hit and cache miss — the two outcomes

> You reach for the note. Either it's there and you read it instantly — or it's blank, and you have to walk to the cabinet after all.

When the answer is in the cache, that's a **cache hit** — fast and cheap. When it isn't, that's a **cache miss** — you do the slow work, and usually store the result so next time hits. These two words describe every cache interaction. The whole game of caching is turning misses into hits.

_Diagram: A hit answers at once. A miss walks to the source and stores the result for next time._

#### Cache hit / miss (found / not found)

- **What it is:** A hit means the answer was in the cache. A miss means it wasn't.
- **How it works:** On a miss you do the slow work and put the result in the cache — so next time is a hit.
- **Example:** First visit to a page: a miss and a database query. Second visit: a hit in milliseconds.
- **Related:** The share of hits is the **hit ratio**, the cache's main score.

### Locality — it works because of repetition

> A coffee shop memorising its regulars' orders — worth it only because the same people ask for the same thing again and again.

Caching pays off when the same answers are needed repeatedly — and almost everything in computing is repetitive. This property is called **locality**: access isn't random but clustered on a few **hot** items. The same popular page, the same user's profile, the same lookup, asked thousands of times. So a small cache of the popular ones can absorb a huge share of the work. No repetition, no reason to cache.

_Diagram: A few hot items take most of the requests; the long tail is rarely asked for._

#### Locality (the hot set)

- **What it is:** The same data is requested again and again.
- **Why it matters:** A small cache of hot items catches a huge share of requests.
- **Example:** A popular page, the same user's profile, the same search.
- **Catch:** No repetition — the cache barely hits and just wastes memory.
- **Related:** Locality is what makes a high **hit ratio** possible.

> **The framing question:** "Is this answer expensive to produce and asked for repeatedly — the two conditions that make remembering it worth the trouble?"

> A cache keeps a fast copy of an expensive answer. A hit is reading the note; a miss is the walk to the cabinet. The job is turning misses into hits.

## 2. Caches are everywhere

Caching isn't one thing in one place — it's a pattern repeated at every layer between a user and the data. The closer the copy sits to who needs it, the faster it is.

### Cache Hierarchy — the closer the cache, the faster the hit

> Supplies you keep on your desk, in the room, in the building, and in a warehouse across town — the nearer it is, the quicker you get it, but the less you can store.

There's a ladder of caches between a user and the truth — a **cache hierarchy**: the **browser** holds files on your device, a **CDN** holds copies near your city, the **application** keeps hot data in memory, and the **CPU** has tiny caches nanoseconds away. Nearer caches are faster but smaller. A request tries the closest first and falls back outward on a miss.

_Diagram: A request goes from the nearest cache outward. Closer is faster, but smaller._

#### Cache Hierarchy (layers of caches)

- **Problem:** One cache can't be near, fast, and big all at once.
- **Idea:** A chain of caches: the near one small and fast, the far one big and slower.
- **Example:** Browser → CDN → app cache (Redis) → database.
- **Cost:** More places where a stale copy can hide.
- **Related:** The layers are the **CDN**, the **in-memory cache**, and CPU caches.

### In-memory Cache (Redis) — the workhorse

> A clerk who keeps the most-asked files on the desk in arm's reach, instead of fetching each one from the basement archive every time.

Most apps put a dedicated **in-memory cache** — a tool like **Redis** or **Memcached** — between the application and the database. Memory is dramatically faster than disk, so keeping hot results there turns a slow database query into a near-instant read. When people say "add a cache" to speed up a backend, this is usually what they mean.

_Diagram: Redis keeps key → value pairs in RAM. The app only goes to the on-disk database on a miss._

#### In-memory Cache (Redis, Memcached)

- **Problem:** Database queries on disk are slow, and the same ones repeat.
- **Idea:** Keep hot results in RAM, looked up by key.
- **Example:** The key `user:42` holds a profile; the app reads it from Redis instead of the database.
- **Cost:** One more service; memory is limited; copies can go stale.
- **When to use:** To speed up a backend in front of a slow source of truth.
- **Related:** Usually filled with the **cache-aside** pattern.

### CDN — the web cached near the user

> Popular books stocked in local libraries everywhere, so no one has to mail away to a single central archive.

A **CDN** (content delivery network) is caching applied to geography: it keeps copies of your pages, images, and files on servers around the world (**edge** servers), serving each user from a nearby one. This is why a global site loads quickly everywhere instead of only near its **origin** server. It's the same hit/miss idea — the copy is just spread across the map to beat distance.

_Diagram: Users get the copy from the nearest edge. An edge only goes to the origin on a miss._

#### CDN (content delivery network)

- **Problem:** The server is in one country, so far-away users wait on distance.
- **Idea:** Keep copies on edge servers all over the world.
- **Example:** A site's images are served from a city near the user, not from the origin.
- **Cost:** Copies around the world go stale too; you need a way to refresh them.
- **When to use:** Static files, pages, and assets for users in many places.
- **Related:** One of the layers of the **cache hierarchy**.

> **The layers question:** "At which layer — browser, CDN, app memory, database — should this answer be cached, given who asks for it and how close I can put it to them?"

> Caching is a pattern repeated at every layer: browser, CDN, in-memory store, CPU. Closer is faster but smaller — and a miss falls outward to the next.

## 3. The hit ratio is the point

A cache is only worth its complexity if it's actually catching most requests. One number — the hit ratio — tells you whether your cache is earning its keep.

### Hit Ratio — the score that matters

> A goalkeeper is judged by the share of shots they stop. A keeper who saves 95% is transformative; one who saves 10% barely changes the game.

The **hit ratio** is the fraction of requests served from the cache rather than the slow source. A 95% hit ratio means only one request in twenty reaches the database — a massive reduction in load and latency. A 10% hit ratio means the cache is mostly overhead. This single number is how you judge whether a cache is working.

_Diagram: 95%: one request in twenty reaches the database. 10%: the cache catches almost nothing._

#### Hit Ratio (share of hits)

- **What it is:** hits ÷ (hits + misses) — the share of requests served from cache.
- **Example:** 95% — 1 request in 20 reaches the database. 10% — the cache barely helps.
- **Why:** The main way to tell if a cache works, and the main lever you tune.
- **Related:** Rises with **locality** and smart **eviction**; drops with a **cold cache** and a short **TTL**.

### Cold and Warm Cache — a cold cache has to warm up

> A new shop with empty shelves serves no one fast at first — it stocks up as customers ask, until the popular items are always on hand.

Right after it starts, a cache is **cold** — empty, so every request misses and goes to the slow source. As real traffic flows, it fills with popular answers and becomes **warm**, and the hit ratio climbs. This is why performance can look bad right after a restart or deploy, then settle. Some systems **pre-warm** the cache deliberately, loading known-hot data before users arrive.

_Diagram: After a restart the hit ratio starts at zero and climbs. A pre-warmed cache starts high._

#### Cold / Warm Cache (pre-warming)

- **What it is:** Cold — an empty cache, everything misses. Warm — filled, and hitting.
- **Example:** After a deploy the site is slow for a few minutes until the cache fills.
- **Catch:** Restarting every node at once sends the full load to the database.
- **Fix:** **Pre-warm**: load the hot data before users arrive.
- **Related:** Explains the **hit ratio** dips after restarts.

### Memory–Speed Trade-off — a cache trades memory for speed

> Renting a bigger desk so more files fit within arm's reach — it costs more space, but you walk to the cabinet far less.

Caching isn't free: you spend **memory**, which is limited and costs money, to save **time**. A bigger cache holds more and hits more often, but you can't cache everything — so the art is caching the _right_ things: the hot, expensive, repeatedly-asked answers that give the most speed per byte stored. A cache is a deliberate **trade-off**.

_Diagram: You pay in memory and buy time. The hit ratio tells you if the deal pays off._

#### Memory–Speed Trade-off (memory for time)

- **Idea:** Pay with memory to make fewer trips to the slow source.
- **Example:** More RAM for Redis — more keys fit, more hits.
- **Cost:** Memory is limited and costs money; you can't cache everything.
- **When to use:** Cache what gives the most speed per byte: the hot and the expensive.
- **Related:** The **hit ratio** measures the payoff; **eviction** frees the space.

> **The ratio question:** "What share of requests is this cache actually serving — and is that ratio high enough to justify the memory it costs?"

> The hit ratio is the cache's report card. You spend memory to buy speed — so cache the hot, expensive answers that earn the most hits per byte.

## 4. Keeping it fresh

A remembered answer can go out of date while you're still trusting it. Knowing when to stop trusting the copy is the central, genuinely hard problem of caching.

### Stale Data — the price of caching

> That phone number you jotted on a sticky note is gold — right up until your friend moves and the note quietly becomes wrong.

The flip side of remembering an answer is that the real answer can change while your copy doesn't. **Stale** data is a cached value that no longer matches the truth — the old price, the deleted post, last hour's stock count. Every cache risks serving stale data, and deciding how much staleness you can tolerate is the first real design question of any cache.

_Diagram: The price changed at the source, but nobody updated the cached copy — it went stale._

#### Stale Data (out-of-date copy)

- **What it is:** A cached value that no longer matches the source.
- **Example:** The old price, the deleted post, last hour's stock count.
- **Why it happens:** The truth changed; the copy didn't.
- **Related:** Bounded by **TTL** and **invalidation**; how much is OK is set by the **staleness budget**.

### TTL — let it expire on a timer

> Milk stamped with a use-by date — after it, you don't trust it without checking, even if it still looks fine.

The simplest freshness tool is a **TTL** (time to live): each cached entry gets an expiry, and after it the entry is treated as gone, forcing a fresh fetch. A short TTL means fresher data but more misses; a long TTL means more hits but more staleness. Choosing the TTL is choosing your exact spot on the freshness-versus-speed trade — per kind of data, based on how fast it really changes.

_Diagram: Until the TTL runs out, the answer comes from cache. After that, the next request fetches fresh data._

#### TTL (time to live)

- **Problem:** A copy can go stale and the cache doesn't know.
- **Idea:** Give every entry a use-by time; after it, fetch again.
- **Example:** An exchange rate cached with a 60-second TTL: never older than a minute.
- **Cost:** A short TTL means more misses; a long one means more staleness.
- **When to use:** Almost always, as the baseline safety net; tune it per kind of data.
- **Related:** A hot key expiring for everyone at once causes a **cache stampede**.

### Cache Invalidation — why this is famously hard

> Knowing the instant a fact changed somewhere else in the world, so you can tear up your note at exactly the right moment — easy to say, maddening to do.

There's a running joke that there are only two hard problems in computer science, and **cache invalidation** — knowing when a cached value must be thrown out — is one of them. It's hard because the cache often doesn't know the underlying data changed; the change happened somewhere else. The next chapter is the set of strategies people use to fight this exact problem.

_Diagram: One service changes the database, another reads the old copy from cache. Who tells the cache?_

#### Cache Invalidation (throwing out the copy)

- **Problem:** The data changed somewhere else, and the cache doesn't know.
- **Idea:** Throw out or refresh the copy when the truth changes.
- **Example:** After a price change, delete the product's key from the cache.
- **Cost:** You have to find every place the copy lives, and miss none.
- **Related:** Strategies: **cache-aside**, **write-through**, **write-around**; safety net: **TTL**.

> **The freshness question:** "How stale can this data safely be — and is a simple TTL enough, or do I need to actively throw the copy out when the truth changes?"

> Every cached answer can go stale. A TTL expires it on a timer — and knowing exactly when to invalidate is one of computing's genuinely hard problems.

## 5. Invalidation and eviction

Two forces decide what's in a cache and whether it's trustworthy: how you update it when the truth changes, and how you make room when it's full. Both have named strategies worth knowing.

### Cache-aside — the app fills the cache

> You check your notepad first; if it's blank, you walk to the cabinet, read the file, and jot the answer down before carrying on.

The most common pattern is **cache-aside** (also called **lazy loading**): on a read, the app checks the cache; on a miss, it fetches from the source, stores the result, and returns it. The cache fills on demand with exactly what's actually requested. It's simple and popular — and its weak spot is staleness, since a value sits in the cache until something expires or invalidates it.

_Diagram: Cache-aside step by step: ask the cache → miss → read the database → store in cache → return._

#### Cache-aside (lazy loading)

- **Problem:** You need to fill the cache without knowing in advance what will be asked.
- **Idea:** The app does it: check the cache, on a miss read the database and put the result in the cache.
- **Example:** `GET user:42` → miss → `SELECT` from the database → `SET user:42` with a TTL.
- **Cost:** A value can be stale until its TTL runs out or someone deletes it.
- **When to use:** The default for most caches in front of a database.
- **Related:** Often paired with **TTL**; on writes it's complemented by **write-through**.

### Write-through and Write-around — keeping writes consistent

> When a fact changes, you can update the desk note at the same moment you update the master file — or skip the note and let it be re-fetched fresh next time.

When data is _written_, you choose how the cache keeps up. **Write-through** updates the cache and the source together, so the cache is never stale (at the cost of slower writes). **Write-around** writes only to the source and lets the cache miss and reload later, avoiding caching data nobody re-reads. Which you pick depends on your read/write mix.

_Diagram: Write-through writes to cache and database at once. Write-around writes only to the database; the cache catches up on a miss._

#### Write-through / Write-around (write policies)

- **Problem:** On a write, the cache and the source drift apart.
- **Idea:** Write-through — update cache and database together. Write-around — write to the database only.
- **Example:** A profile that's re-read right away — write-through. Logs that are hardly ever read — write-around.
- **Cost:** Write-through — slower writes. Write-around — a miss right after the write.
- **When to use:** Based on your read/write mix.
- **Related:** Write-side ways to do **cache invalidation**.

### Eviction (LRU, LFU) — deciding what to drop when full

> A small desk that's full — to add a new file you must put one away, so you remove the one you haven't touched in ages, not the one you use hourly.

A cache has limited space, so when it fills it must **evict** something. The most common policy is **LRU** (least recently used): drop whatever hasn't been touched in the longest time, on the bet that it won't be needed soon. Others exist — **LFU** (least frequently used) drops the least frequently used. Eviction is how a small cache automatically keeps the hot items and sheds the cold ones, without growing forever.

_Diagram: The cache is full and F arrives. Under LRU, B goes — nobody has touched it for longest._

#### Eviction (LRU, LFU)

- **Problem:** The cache is out of space, and new data keeps arriving.
- **Idea:** Drop what's least likely to be needed soon.
- **Example:** LRU — drop the longest-untouched. LFU — drop the least used.
- **Cost:** Sometimes it drops what's about to be asked for — an extra miss.
- **Related:** Keeps the **hit ratio** up without growing memory. Not the same as **invalidation**: that's about wrong data, eviction is about space.

> **The strategy question:** "When the underlying data changes, how does this cache find out — and when it's full, is it dropping the genuinely cold entries?"

> Invalidation decides when a cached value is wrong; eviction decides what to drop when space runs out. Cache-aside, write-through, LRU — names for those two jobs.

## 6. When caching bites

Caching's power comes with sharp edges. The classic failures aren't exotic — they're predictable, they have names, and knowing them is half of avoiding them.

### Cache Stampede — when a hot key expires

> A popular item sells out, and the instant it does, a hundred customers all rush the counter to ask for it at once — overwhelming the one clerk who restocks.

When a popular cached entry expires, every request that wanted it misses _at the same moment_ and all hit the slow source together — a **cache stampede** (or **thundering herd**). The database, shielded for hours, suddenly takes the full crowd at once and can buckle. The fixes are known — let one request refresh while others wait, or stagger expiries — but you have to anticipate it: a stampede appears exactly when traffic is highest.

_Diagram: A hot key expired — every request rushes the database at once. Below: the two known fixes._

#### Cache Stampede (thundering herd)

- **Problem:** A hot key expires, and every request misses and hits the database at once.
- **Example:** The home page expires at peak traffic — thousands of requests rebuild it at the same time.
- **Fix:** One request refreshes while the rest wait; or random spread on the TTL (jitter).
- **When to think:** For every hot key with a **TTL**.
- **Related:** A side effect of **TTL** on popular data.

### Stale Reads — fast, confident, and wrong

> Reading a price off an old sticky note and quoting it confidently — the number is delivered instantly, and it's the wrong number.

A cache will happily serve a **stale** value fast and with full confidence — a **stale read**. Usually that's fine — a slightly old view count harms no one. But for data where correctness is critical — a bank balance, inventory, permissions — a stale read can be a real bug. The skill is knowing which data tolerates staleness and which must always be fresh, and never caching the second kind carelessly.

#### Stale Read (serving the past)

- **Problem:** The cache serves an old value, fast and confidently.
- **Harmless:** A view count a minute out of date.
- **A real bug:** A bank balance, inventory, permissions.
- **Fix:** Decide up front which data tolerates staleness and which doesn't.
- **Related:** How **stale data** shows up; treated with a **staleness budget**.

### What Not to Cache — some things shouldn't be cached at all

> You don't keep a photocopy of a document that's rewritten every minute, or of someone's private letter on a shared desk — the copy is wrong, or it shouldn't be there.

Not everything belongs in a cache. Data that **changes constantly** gives a poor hit ratio and frequent staleness. **Sensitive or per-user** data risks leaking if a shared cache hands one user's copy to another. And **rarely-requested** data just wastes space. Knowing what _not_ to cache is as important as knowing what to cache.

_Diagram: Three kinds of data that don't belong in a cache. Below: how a shared cache hands user A's data to user B._

#### What Not to Cache (the skip list)

- **Fast-changing:** Poor hit ratio and constant staleness.
- **Sensitive:** Per-user and secret data in a shared cache can reach the wrong user.
- **Unpopular:** Rarely asked for — it only takes up space.
- **Related:** The flip side of the **cache target**.

> **The trap question:** "What happens to my slow source the instant a hot entry expires — and is anything in this cache too fresh-critical or too sensitive to be there at all?"

> Caching's classic bites are named: stampedes when a hot key expires, stale reads served with false confidence, and caching things that never should be.

## 7. Using it well

Caching is a power tool: enormous speed for a little memory, paid for with the risk of serving the past. Used deliberately, it's one of the best trades in computing.

### Cache Target — cache the hot, expensive, and slow-changing

> You memorise the regulars' usual orders and the directions you give ten times a day — not the one-off requests or the things that change by the minute.

The ideal **cache target** is **frequently read, expensive to produce, and rarely changed** — that combination yields the most speed for the least staleness risk. A popular page built from a slow query, recomputed identically all day, is perfect. A constantly-changing, rarely-read, sensitive value is the opposite.

_Diagram: All three conditions together make the ideal cache target._

#### Cache Target (what to cache)

- **Idea:** Read often + expensive to produce + rarely changed.
- **Example:** A popular page built from a slow query, identical all day.
- **Counter-example:** A constantly-changing, rarely-read, sensitive value.
- **Related:** The opposite of **what not to cache**; it gives a high **hit ratio**.

### Staleness Budget — decide it up front

> Agreeing in advance how out-of-date is acceptable — a weather widget can be minutes old; a bank balance cannot be seconds old.

Before caching anything, decide how much **staleness** it can tolerate — that's its **staleness budget**. That choice drives everything else — the TTL, whether you need active invalidation, whether it's safe to cache at all. Make it explicit per kind of data. "How wrong is it allowed to be, and for how long?" is the question that turns caching from a source of mysterious bugs into a controlled, deliberate trade.

_Diagram: On the left, data that tolerates staleness; on the right, data that must always be fresh._

#### Staleness Budget (how old is OK)

- **Problem:** Without an explicit decision, staleness shows up as mysterious bugs.
- **Idea:** For each kind of data, decide up front how old it may be.
- **Example:** Weather — minutes is fine. A bank balance — not a second.
- **What it sets:** The **TTL** length, whether you need **invalidation**, whether to cache at all.
- **Related:** The answer to the risk of **stale data** and **stale reads**.

### How the concepts connect

> Two pans of a scale: speed on one, freshness on the other. Every concept in this course moves one of them.

All of caching is a tug-of-war between **speed** and **freshness**. On the left, what raises the **hit ratio**: locality, a warm cache, sensible eviction. On the right, what keeps **stale data** in check: the staleness budget sets the **TTL**, and **invalidation** throws out what's wrong. A short TTL is fresher but hits less; on a hot key, the same TTL can trigger a **stampede**.

_Diagram: Speed forces on the left, freshness forces on the right. The budget sets the TTL; the TTL bounds staleness and can trigger a stampede._

#### Before you add a cache

- **Is the data hot** — asked for repeatedly enough to give a real hit ratio?
- **Is it expensive** to produce, so a hit actually saves meaningful work?
- **How stale can it be** — what's the TTL, and do I need active invalidation?
- **What happens when a hot entry expires** — could it cause a stampede?
- **Is it safe to cache** — not per-user secret data in a shared cache?
- **How will I know it's working** — am I measuring the hit ratio?

#### Signs you cache well

- You can name the **hit ratio** of your important caches.
- Each cached thing has a **deliberate TTL** matched to how fast it really changes.
- Nothing **per-user or secret** sits in a shared cache by accident.
- Your hot keys won't **stampede** the source all at once on expiry.
- You cache the **hot, expensive, slow-changing** answers — and skip the rest.

## Cheat sheet: all 20 concepts

### Basics

- **Cache** (the notepad): A fast copy of an expensive answer, so the work isn't done twice.
- **Cache hit / miss** (found / not found): The answer was in the cache — or you had to go to the source.
- **Locality** (the hot set): The same data is asked for again and again — that's why caches work.

### Layers

- **Cache Hierarchy** (layers of caches): Browser → CDN → app memory → database. Closer is faster, but smaller.
- **In-memory Cache** (Redis, Memcached): Hot data in RAM in front of a slow database.
- **CDN** (content delivery network): Copies of files and pages on servers near the users.

### Hit ratio

- **Hit Ratio** (share of hits): The share of requests served from cache. The cache's main score.
- **Cold / Warm Cache** (pre-warming): An empty cache misses everything; a filled one hits. Pre-warm loads it ahead of time.
- **Memory–Speed Trade-off** (memory for time): Pay in memory, buy time. Cache the most speed per byte.

### Freshness

- **Stale Data** (out-of-date copy): The copy no longer matches the truth.
- **TTL** (time to live): An entry's lifetime; after it, fetch again.
- **Cache Invalidation** (throwing out the copy): Drop the copy when the truth changes. Famously hard.

### Strategies

- **Cache-aside** (lazy loading): The app checks the cache, reads the database on a miss, and stores the result.
- **Write-through / Write-around** (write policies): Write to cache and database together — or to the database only.
- **Eviction (LRU / LFU)** (making room): When full, drop the longest-untouched or least-used entry.

### Traps

- **Cache Stampede** (thundering herd): A hot key expires — everyone hits the database at once.
- **Stale Read** (serving the past): Fast, confident, and wrong. Dangerous for money, stock, permissions.
- **What Not to Cache** (the skip list): Fast-changing, sensitive, unpopular.

### Using it well

- **Cache Target** (what to cache): Read often, expensive to make, rarely changed.
- **Staleness Budget** (how old is OK): Decide up front how old data may be. It sets the TTL and invalidation.

> Caching trades a little memory for enormous speed, at the risk of serving the past. Done well, it's deliberate: the right answers, with a staleness budget you chose on purpose.

End of express course · 7 chapters · 20 concepts

Next comes practice: find the slowest repeated operation in something you've built — a query, an API call, a computed page — and put a small cache in front of it with an explicit TTL. Then watch the hit ratio and the latency change. The trade becomes real the moment you measure it. But hold one idea above the rest: caching is just remembering an expensive answer instead of redoing the work — and every hard part is really one question, asked honestly: when is the thing I remembered no longer true?
