Cache-Aside
A caching pattern where the application checks the cache first; on a miss, it fetches from the database and populates the cache. Also called lazy loading.
What is Cache-Aside?
In short
Cache-aside is a caching pattern where the application checks the cache first, and on a miss it reads from the database, then writes that value into the cache before returning it. The cache stays out of the read path until something actually asks for the data, which is why it is also called lazy loading.
What cache-aside actually is
Cache-aside puts the application in charge of the cache. The cache (something like Redis or Memcached) and the database (something like Postgres or MySQL) do not talk to each other. The application code sits between them and decides what to read and write where.
The contract is simple. To read a value, look in the cache. If it is there (a cache hit), return it. If it is not (a cache miss), read from the database, copy the result into the cache, and return it. Only data that someone actually requested ever ends up in the cache, so it fills lazily over time.
This is the opposite of read-through caching, where the cache library itself fetches from the database on a miss. In cache-aside the cache is a dumb key-value store and your code owns every step. That extra control is the whole point of the pattern.
How a read and a write flow through it
On a read, the app issues a GET to the cache. A miss triggers a SELECT against the database, then a SET to write the value into the cache with a time-to-live, often 60 seconds to a few hours depending on how stale the data is allowed to get. The next read of the same key hits the cache and skips the database entirely.
Writes are where teams get into trouble. The standard cache-aside approach is to write to the database, then invalidate (delete) the cached key rather than update it. The next read repopulates the cache with fresh data. Deleting is safer than updating because two concurrent writers updating the same key can leave a stale value behind, while a delete just forces a clean reload.
Because the cache fills on demand, the first request for any key is always slow (it pays the database round trip plus the cache write). This is a cold cache. After warm-up, hit rates of 90 to 99 percent are common for read-heavy workloads, and the database only sees the small fraction of traffic that missed.
When to use it and what it costs you
Use cache-aside when reads heavily outnumber writes and you can tolerate data being slightly stale for the length of the TTL. User profiles, product catalogs, and configuration are classic fits. It is the default caching pattern for most applications because it is resilient: if the cache goes down, the app still works by reading straight from the database, just slower.
The trade-offs are real. You write the cache logic by hand in every read path, so it is easy to forget invalidation somewhere and serve stale data. There is a race condition window where a read can repopulate the cache with an old value just after a write deleted it, so for strict correctness you sometimes need short TTLs or versioned keys. And cold caches mean a cluster restart or a flushed cache can briefly slam the database with a thundering herd of misses.
Compared to write-through (write to cache and database together) or write-behind (write to cache, flush to database later), cache-aside trades guaranteed freshness for simplicity and fault tolerance. Most teams pick it and accept eventual consistency bounded by the TTL.
A concrete example
Picture an e-commerce product page that gets read thousands of times per second but is edited maybe once a day. Without a cache, every page view runs a database query. With cache-aside, the first view of product 12345 misses, reads the row, and stores it in Redis under the key product:12345 with a 10 minute TTL.
Every view for the next 10 minutes is served from Redis in well under a millisecond, and the database sees zero load for that product. When an admin edits the price, the application updates the database row and deletes product:12345 from Redis. The next shopper triggers a fresh read that repopulates the cache with the new price.
This is roughly how large catalogs, session stores, and API response caches are built. The pattern scales because the database only handles misses and writes, which is a tiny slice of total traffic.
Where it is used in production
Redis
The most common cache-aside store; apps GET a key, fall back to the database on a miss, then SET the value with a TTL.
Amazon DynamoDB Accelerator (DAX)
AWS documents cache-aside as the standard pattern for fronting DynamoDB with an in-memory cache for read-heavy tables.
Facebook (Memcached)
Runs a massive cache-aside layer over MySQL, reading from Memcached first and deleting keys on writes to keep data fresh at scale.
Netflix (EVCache)
Uses a Memcached-based cache-aside tier so most reads never touch the backing data store.
Frequently asked questions
- What is the difference between cache-aside and read-through caching?
- In cache-aside the application code reads from the database on a miss and writes the value back into the cache itself. In read-through, the cache library handles that fetch automatically, so the app only ever talks to the cache. Cache-aside gives you more control; read-through hides the logic.
- Why delete the cache key on a write instead of updating it?
- Deleting is safer under concurrency. If two writers update the same key in different orders, the cache can end up holding the older value. Deleting forces the next read to repopulate from the database, which is the source of truth, avoiding that stale-write race.
- What happens on the first request to a key?
- It is a cache miss, so it is slow. The app pays a database read plus a cache write before returning. This is a cold cache. After that key is requested once, later reads hit the cache until the TTL expires or the key is invalidated.
- Is cache-aside data always up to date?
- No. It gives eventual consistency bounded by the TTL and your invalidation logic. A cached value can be stale until it expires or a write deletes it. If you need strict freshness, use short TTLs, explicit invalidation on every write, or a write-through pattern instead.
- What is a thundering herd in cache-aside?
- When a popular key expires or the cache restarts, many requests miss at once and all hit the database simultaneously. Mitigations include staggered TTLs, request coalescing (single-flight), or pre-warming hot keys.
Learn Cache-Aside hands-on
This page explains the idea. The full lesson lets you step through the ring as servers join and leave, read the implementation, and check yourself with a quiz. It is one of 760+ lessons in the System Design Masterclass, from your first API call to distributed consensus. Eleven Foundation lessons are free, no signup. Lifetime access is ₹499 in India or $7.99 worldwide, one payment, no subscription.
Related lessons
Lessons that touch on Cache-Aside as part of a larger topic.
Cache-Aside Pattern
The most common caching pattern in production, your application owns the cache, not the other way around
foundation · caching strategies
Read-Through Cache
Let the cache handle database reads for you, the application never talks to the database directly
foundation · caching strategies
See also
Related glossary terms you might want to look up next.
Caching
Storing frequently accessed data in a faster storage layer so you don't have to fetch it from the original (slower) source every time.
Write-Through Cache
A caching pattern where every write goes to both the cache and the database simultaneously. Ensures consistency but adds write latency.
Write-Behind Cache
A caching pattern where writes go to the cache first and are asynchronously flushed to the database later. Fast writes but risks data loss on cache failure.
CDN
A network of servers distributed globally that caches content close to users. Netflix uses CDNs to stream video from servers near you, not from one central location.
Cache Eviction
The process of removing entries from a cache when it's full. Common policies: LRU (least recently used), LFU (least frequently used), FIFO (first in, first out).
TTL
Time To Live: how long a cached entry, DNS record, or packet is valid before it expires and must be refreshed or discarded.