Core Patterns: Aside, Through & Behind
Why Cache
Caching avoids repeating expensive work — a slow query, a network call, a costly computation — by storing and reusing a previous result. It trades memory/storage and potential staleness for lower latency and reduced load on the underlying resource. Every strategy below is a different answer to: when do we read/write the cache, and when do we trust it?
Cache-Aside (Lazy-Loading)
async function getUser(id) {
const cached = await cache.get(`user:${id}`);
if (cached) return cached;
const user = await db.users.findById(id);
await cache.set(`user:${id}`, user, { ttl: 300 });
return user;
}
// application owns the miss-handling logic — simple, but the first
// request after a miss/eviction always pays full source latencyRead-Through
The cache itself sits in front of the data source and loads missing data on a miss, transparent to the caller — pushing the miss-handling logic into the caching layer (via a loader function) instead of application code.
Write-Through vs. Write-Back
Write-through writes to cache AND the source synchronously on every write — consistent immediately, at the cost of write latency. Write-back writes to cache immediately and flushes to the source asynchronously later — faster, but risks data loss if the cache fails before flushing.
Eviction Policies
LRU evicts the entry unused for the longest time. LFU evicts by lowest access count. FIFO evicts in pure insertion order. Choice depends on access pattern — LRU suits most general-purpose caches.
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free