Eye Training · Caching and Memoization
A cache is a copy. Every caching bug is a copy that is wrong, shared, stale, unbounded, or rebuilt by everyone at once.
Part 2 · Surface 17. Bug counts are hidden and some snippets are clean. See Start Here for how to use these drills.
J · The basics
Bug hunt
J · Product listing
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Cache the settings
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Memoize
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Cached user
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
M · Three years in, these should jump out
Bug hunt
M · Unread count
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Feature flags
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Exchange rates
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Render markdown
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Update an email
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Dashboard
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Load once
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
S · Where seniors stand out
Bug hunt
S · Homepage
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 2 min
Bug hunt
S · Profile page
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
S · After the deploy
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 2 min
Bug hunt
S · Permissions cache
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 2 min
What your eye checks
Whenever you see a cache, a Map used as one, or a memoize, ask:
- Is every input in the key? Page, filters, locale, user, tenant, version. A missing one means wrong data; a missing user means leaked data.
- When does it expire, and what clears it on change? No TTL plus no invalidation means stale forever.
- Write first, then invalidate. Deleting the key before the write lets a reader cache the old value.
- Is the hit check correct for every value?
if (cached)treats0,''andfalseas misses. - Can a caller mutate the cached value? Shared objects need copying or freezing.
- Are failures cached? A rejected promise or an error result shouldn't stick.
- Is it bounded? A
Mapthat only grows is a memory leak with a delay. - What happens when a hot key expires? Stampede: lock, single-flight, serve stale, jitter.
- Is it per instance? In-process caches differ across instances and survive role changes; who tells them to forget?
- HTTP:
publicversusprivate; personal responses must never go to a shared cache.
Tells
| You see | Ask |
|---|---|
| A key built from some of the inputs | What else changes the result? |
| A key with no user or tenant | Whose data is this? |
redis.set(key, value) with no EX | When does it expire? |
del before update | What does a reader cache in between? |
if (cached) | What if the value is 0 or ''? |
.push / assignment on something from a cache | Shared copy? |
cache.set(key, promise) | What if it rejects? |
new Map() at module level, only set | Who removes entries? |
| A slow build after a miss | What do the other requests do meanwhile? |
Cache-Control: public on a logged-in page | Who else gets it? |
| A shape change and an existing cache | Versioned key? |
Go deeper
- Controlling Concurrency: Part 4, single-flight and the rejected-promise trap
- SD 1 · Caching: cache-aside, invalidation and stampedes at the system level
- Previous surface: fetch and the network · Next: Shared state and races