Understand the building blocks / CHAPTER 12
Caching fundamentals
Use cached copies to reduce work while defining freshness, invalidation, and miss behavior.
Builds on System design building blocks, Functional and non-functional requirements.
- Explain hits, misses, eviction, and expiration.
- Calculate an approximate backend-load reduction.
- Prevent stampedes and unsafe stale responses.
01Reuse a result without creating a second truth
A customer opens product 42. The database holds the current product record. If every read repeats the same expensive database lookup, the application can save a reusable copy in a cache.
Define the copy before adding it:
- Name the entry
product:42so readers of this product find the same copy. - Save the product data and its version inside that entry. Version
7means a particular saved revision; an update may produce version8under the same entry name. - Decide how old the copy may be for this operation. A public description may tolerate delay; permission or the final stock claim may require current state.
- Define how a read proceeds when no usable copy exists.
Finding a usable entry is a hit. Having to load or compute the value is a miss. The hit ratio is the number of hits divided by the number of lookups for a stated workload.
Calculate both normal and failure demand:
- At 10,000 reads per second and 95% hits, 5% miss.
- Assuming one database lookup per miss,
10000 × 0.05 = 500lookups per second reach the database. - If the database supports 2,000 lookups per second, this warm-cache workload fits.
- If every entry disappears, all 10,000 reads may miss. That is five times the database’s useful capacity.
The cache saves repeated work, but adds memory, network operations, and another failure case. A high overall hit ratio can also hide one very expensive miss or one popular entry that overloads its assigned cache machine.
02Follow a hit, a miss, and a write
In a cache-aside design, the application handles a missing entry:
- Look up
product:42in the cache. - If a usable copy exists, return it under the operation’s freshness and permission rules.
- Otherwise read the product from the database, save a reusable copy, and return the result.
Distinguish three reasons a copy disappears:
- Expiration ends its permitted reuse after a time limit, called its time to live or TTL.
- Eviction removes an entry to free cache capacity. Least recently used favors entries read recently; least frequently used favors entries read repeatedly. Implementations may approximate these rules.
- Invalidation removes or disables an entry after the underlying data changes.
A 60-second TTL does not lock the database record. If the record changes just after a copy is saved, that copy can be stale for almost a minute. Invalidation helps, but does not by itself solve this ordering problem:
- A reader loads version
7from the database, then pauses before saving the cache copy. - A writer saves version
8in the database. - The writer removes the cached entry.
- The reader resumes and saves its older version
7underproduct:42.
The old value has returned after removal. To prevent this particular stale fill, the cache update needs information that survives removal:
- Retain a marker saying that version
8is the minimum acceptable version. - When a reader tries to save a copy, check that marker and insert the value as one indivisible operation. Reject version
7. - For this example, retain the minimum-version marker for the product’s lifetime, separately from the cached value’s expiry and eviction. A fill that cannot read that marker must not install an older copy. This costs retained version metadata; removing that evidence along with the value loses the protection.
Use a read or update that establishes current state where correctness demands it. Best-effort invalidation and a short TTL are insufficient authority for a revoked permission or a final inventory claim.
03Control the miss path and choose permitted staleness
Suppose 100 readers request the same popular product after its entry expires. If each immediately queries the database, they repeat the same expensive work. This burst is called a cache stampede.
Control the work in a deliberate order:
- Let one application fetch the missing product while the other readers share that in-progress result. This is request coalescing.
- Limit how many database fetches run at once across keys. One fetch per key can still overload the source when many different products miss.
- Bound how long callers wait. Decide whether each operation may receive an older copy or must fail when a fresh result is unavailable.
- Spread future expiration times across keys by adding small variations, called expiry jitter. This reduces simultaneous expirations, but does not merge readers already missing one key.
Other choices need explicit costs:
- Background refresh can prepare a copy before readers wait, but its work still counts against source capacity.
- Briefly caching a known absence saves repeated lookups. If a record is created a second into a 30-second negative entry, readers may keep seeing absence until that entry is updated or expires.
- Keeping extra copies of a popular entry can spread cache load. Every copy adds freshness and invalidation work.
- Serving an older public view count may be acceptable. Serving an old private access grant after revocation can expose data. A useful hit ratio does not justify that permission failure.
For a cache restart, establish source limits before allowing all misses through. Warm useful entries gradually and test the real cold path. Observe served age, database traffic, refresh errors, and the oldest waiting request as well as hit ratio. The aim is less repeated work while preserving the promised response, including when copies are missing.
A late reader can refill stale data
Follow the numbered arrows
- Reader R → Writer Wsource changes after R read
- Writer W → Invalidationdatabase-first invalidation
- Invalidation → R resumesreader was still in flight
- R resumes → Cache populationlate population attempt
- Checked cache fill → Cache populationcompare retained version before saving
Trace the diagram in words
- The reader loads version 7 but has not saved it in the cache.
- The writer saves version 8 and removes the cache entry.
- The paused reader resumes and attempts to save version 7.
- A retained minimum-version marker can reject 7 only if the fill checks that marker as one indivisible operation.
DRAW. CALCULATE. EXPLAIN.
Budget a cache restart
20 minutes · guided practice
A service receives 12,000 reads per second. A warm cache has a 96% hit ratio, and the database supports 1,500 lookups per second.
- Calculate normal database demand and demand with an empty cache.
- Explain how to protect the database during restart.
- Trace how a paused reader can restore an old value after a writer invalidates the entry, and explain a real prevention mechanism.
Compare the worked solution
- Warm misses are
12000 × 0.04 = 480database lookups per second. - With an empty cache, up to 12,000 reads per second may miss. That is
12000 / 1500 = 8times the database limit. - Limit simultaneous database work before the surge arrives. Share fetches for the same key and warm useful entries gradually. Bound waiting; serve an older value only where its freshness and permission rules allow it.
- For the race, a reader loads version
7and pauses. A writer saves version8and removes the entry. The reader resumes and saves 7 into the now-empty entry. - To reject that fill, retain a minimum-version marker of 8 and compare it with the proposed value as part of the indivisible fill operation. Retain that marker even when the cached value expires or is evicted. If the marker is unavailable, do not install a copy from an earlier read. A required current read can instead use the database’s suitable read path.
- A short TTL can reduce stale reuse time, but it does not prevent the race.
The checkboxes record your own assessment. The worked solution gives you a way to check the reasoning.
RETRIEVE BEFORE YOU REVEAL
Keep the important ideas.
Say the answer aloud, then turn the card over.
CARD 01What must be defined before adding a cache?
- Identify the original record.
- Define the cache key and saved value.
- State the maximum permitted staleness.
- Explain the miss and cache-failure paths.
A hit must still satisfy the operation’s permission and correctness rules.
CARD 02How do expiry, eviction and invalidation differ?
- Expiration ends reuse after a time limit.
- Eviction frees cache capacity.
- Invalidation removes or disables a copy after a change.
A paused reader can restore an older value after invalidation unless a checked fill operation prevents it.
CARD 03How do I prevent a stampede?
- Share one in-progress fetch for readers of the same missing key.
- Limit simultaneous source fetches across keys.
- Bound waiting and allow old data only where the product permits it.
- Vary future expiration times to avoid many keys expiring together.
CHECK THE REASONING
Can you explain the choice?
Answer every question, then finish for an immediate score and an explanation for each answer. Aim for 80%, then revisit any gaps.
CLOSE THE LOOP
Explain it without the page.
Summarise the mechanism, one trade-off, and one failure mode. Then mark this chapter complete.