Speed up reads with caching
Choose a caching pattern, an eviction policy, and a way to stay fresh.
- Describe cache-aside, write-through, and write-back caching.
- Explain LRU eviction and TTL expiry.
- Recognize invalidation problems such as stale data and stampedes.
A cache keeps a copy of data somewhere faster - in memory rather than on disk, or at the network edge rather than across an ocean. It trades freshness and memory for speed and reduced load on the source of truth. Caches appear at every layer: the browser, a CDN for static assets, an application cache such as Redis or Memcached, and the database’s own buffer pool.
Caching patterns
- Cache-aside (lazy loading): the app checks the cache; on a miss it reads the database and populates the cache. The most common pattern.
- Write-through: writes go to the cache and the database together. Reads are fresh, but writes are slower.
- Write-back (write-behind): writes go to the cache and are flushed to the database later. Fast, but data can be lost if the cache node fails first.
Caches are finite, so they evict. LRU (least recently used) drops the entry untouched for longest; LFU drops the least frequently used. A TTL expires entries after a set time, bounding how stale they can get.
1database = {"user:1": "Ada", "user:2": "Grace"}
2cache = {}
3
4def get(key):
5 if key in cache:
6 return f"{cache[key]} (hit)"
7 value = database[key]
8 cache[key] = value
9 return f"{value} (miss)"
10
11print(get("user:1"))
12print(get("user:1"))
13print(get("user:2"))Ada (miss) Ada (hit) Grace (miss)
The benefit depends on the hit ratio. With a 90% hit ratio, a 1 ms cache, and a 20 ms database, the average read takes 0.9 × 1 + 0.1 × 20 = 2.9 ms - and the database sees only a tenth of the reads. Invalidation is the hard part: when data changes you must update or delete the cached copy, or accept staleness up to the TTL.
Key takeaways
Cache-aside is the default; write-through favors freshness; write-back favors write speed at a durability risk.
LRU and TTL keep a cache bounded in size and staleness.
Always plan invalidation and protect hot keys from stampedes.
Lesson quiz
6 questions · pass with 5 correct · up to 50 XP
Passing this quiz completes the lesson and keeps your streak going. Questions you miss come back in review sessions later.
Practice: simulate system design building blocks
Use small Python programs to estimate capacity and simulate caches, load balancers, hash rings, and rate limiters. These exercises run locally in your browser.
Simulate an LRU cache
Read a capacity, then a line of space-separated keys to access in order. Simulate an LRU cache: a hit moves the key to most recent; a miss inserts it and, if the cache is over capacity, evicts the least recently used key. Print hits=H misses=M, then cache= followed by the keys from least to most recently used, joined by commas.
- Capacity 2
- Capacity 3
Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.
Questions about this lesson
Stuck? Ask. Figured something out? Share it. Explaining is one of the best ways to learn.
Loading posts…