TweakCode
Building Blocks lessons

Caching · Stage 1 of 3

Cache-Aside with LRU Eviction

Serve repeat reads from memory and evict the least recently used key

Foundations

A cache keeps copies of hot data in memory, close to the service, so a repeat read skips the slower store behind it. In cache-aside, the service checks the cache first: a hit returns at once, and a miss reads the store and writes the value into the cache on the way back. The store stays the source of truth; the cache only holds copies.

gethit → answermiss → read3. fillClientAPICache1. checkDatabase2. on a miss
Cache-aside: the API checks the cache first. A hit returns at once; a miss reads the database and fills the cache on the way back.

Memory is limited, so a full cache must evict something. Least recently used, LRU, evicts the key that has gone longest without a read, betting that recent keys will be read again soon. A hash map finds a key in O(1), and a linked list ordered by recency moves a hit to the front and drops the tail.

Take a two-entry LRU cache and reads of keys a, b, a, c. a misses and is filled, b misses and is filled, and a hits and becomes the most recent, so when c misses, the cache evicts b. Three of four reads went to the store here, but on skewed traffic, where a few keys dominate, most reads hit.

cache, oldest first

01
a
c

evicted

0
b
After reads of a, b, a, and c, the hit moved a behind b, so b was the least recent key and was evicted to make room for c.
  • Interfaces

    That lesson writes each endpoint and its row before any box is drawn. These blocks serve those reads and writes.

    Open lesson

Case Scenario

The design brief

Cache the redirect

Short codes are looked up hundreds of times a second, and a handful of codes are looked up far more than the rest. The mapping row rarely changes.

Input
capacity = 2, db = {"a": "/docs", "b": "/blog", "c": "/jobs"}, requests = ["a", "b", "a", "a", "c", "a", "b"]
Output
["miss", "miss", "hit", "hit", "miss", "hit", "miss"]

To see how caching transforms read latency, consider a URL shortener service like bit.ly, where a 7-character short code redirects to a long destination URL: codes are looked up hundreds of times a second, a handful far more than the rest, and a mapping rarely changes. Cache-aside keeps hot codes in memory, and LRU evicts the cold ones.

Short codes are opened hundreds of times a second, but traffic is uneven: a few codes receive most requests and their mappings rarely change. Sending every repeat across the network to the mappings table wastes its limited read capacity and makes visitor latency depend on that table. The database must see well under 10% of redirects even when a handful of codes become hot.

Pro

The rest of this is on Pro

The idea above is free. The walkthrough, the cost, and the practice are on Pro.