System designLoading progress…

Cache-aside

Design a cache key, freshness policy and miss path while calculating load and mean-latency effects.

Cache-aside

In cache-aside the application reads the cache first; on a miss it fetches from the source and stores the result. A miss only says the entry is not cached, not that the record does not exist. The subtle part is concurrency: a slow reader that fetched the old value can store it after a writer has updated the source and deleted the entry, leaving stale data in the cache.

1. read a: miss → fetch from the source, populate the cache 2. read b: miss → fetch from the source, populate the cache 3. read a: hit 4. read a: hit 5. read b: hit source calls 2, hits 3 a miss only means the entry is not cached: the source may well have the record

Cache-aside: read the cache, on a miss fetch from the source and populate. Concurrent misses and write races can put old data back; a version check on populate closes the gap.

Read a sequence, then step through the write race.

Predict first. Does a cache miss mean the source has no record?

Chapter context

A cache serves a previously obtained representation instead of repeating work. Its correctness depends on which requests can share a value and how long that value may remain useful. Fast retrieval of the wrong representation is still an error.

Chapter reference: math, worked example & code

This section belongs to the whole chapter, so it is the same on every lesson in it and may cover a different lesson's topic. The code for the experiment you just ran is inside the experiment itself.

Math and notation

If h is hit probability, t-hit hit-path time and t-miss complete miss-path time:

E[T]=h thit+(1−h)tmiss,Rorigin≈(1−h)R.E[T]=h\,t_{hit}+(1-h)t_{miss},\quad R_{origin}\approx(1-h)R.

The miss time here already includes lookup overhead. Means do not establish tail latency, and background refresh can add origin traffic.

Worked example

At 90% hits, 2-ms hit paths and 50-ms complete miss paths, mean latency is 0.9×2+0.1×50=6.8 ms. For 1000 requests/s, nominal origin demand is 100 requests/s. During a complete cache outage, it could become 1000 requests/s rather than remaining at the normal miss rate.

Reference code

The following example uses the Python standard library and does not call a remote service.

from math import isclose
hit=.9
assert isclose(hit*2+(1-hit)*50,6.8)
assert isclose((1-hit)*1000,100)
assert 1000/100 == 10

Python examples are provided for study and local execution; this page does not execute Python.

Common mistakes

A hit ratio is not a correctness guarantee. Mean latency does not reveal p95. Shared caching requires a safe identity and privacy policy; TTL does not replace authorization.