Pattern · Scaling
Scaling reads
Most systems read far more than they write. The ladder of fixes from indexes to caches, replicas and CDNs, in the order to apply them, and what each costs in freshness.
10 min read
Read-heavy is the most common shape in system design: feeds, product pages, profiles, short links, search suggestions. Ratios of 10:1 to 1,000:1 reads to writes are normal. The pattern is to serve each read from the cheapest place that's fresh enough.
The problem
One database node serves maybe tens of thousands of simple reads a second. A popular product page, a viral short link or a celebrity's profile can exceed that alone, and the database also has to keep up with writes.
The ladder
Apply these roughly in order. Each step costs more complexity than the one before, so stop when the numbers work.
- Make each read cheap. Add the right index, return only the needed columns, remove N+1 queries. A query going from a 200 ms scan to a 1 ms index lookup is a 200× gain for free.
- Denormalize for the hot path. Precompute what a page needs (counts, joined fields) at write time instead of joining on every read.
- Cache in front of the database. Cache-aside in Redis with TTLs. With a 95% hit ratio, the database sees one read in twenty.
- Add read replicas. Spread the remaining reads; accept replication lag.
- Push to the edge. Put cacheable responses and static assets on a CDN, close to users.
- Shard when even the cache misses and replicas can't keep up, usually because the data set itself is too big.
Freshness is the price
Indexes and denormalization
- Always fresh
- No new infrastructure
- Write cost and storage for each index or copy
Pick it when: Always first.
Application cache
- Sub-millisecond reads
- Huge offload
- Stale until TTL or invalidation
- Stampedes on popular misses
Pick it when: Hot keys that tolerate seconds of staleness.
Read replicas
- Full query flexibility
- Lag from ms to seconds
- Read-your-writes needs routing
Pick it when: Broad read load, not just a few hot keys.
CDN
- Closest to users
- Absorbs spikes
- Invalidation is slow and coarse
- Only for shareable responses
Pick it when: Public, identical-for-everyone content.
Hot keys
A cache cluster still sends each key to one node. When a single item is extremely popular:
- Keep a tiny in-process cache in each API server for a second or two.
- Replicate the key under several names (
item:42#1…#8) and read a random copy. - Use request coalescing so only one request per key goes to the database on a miss.
Common mistakes
- Adding a cache before fixing a missing index.
- Caching without TTLs, so bugs in invalidation last forever.
- Reading from replicas right after a write and showing users stale data.
- Ignoring the cold-start case: after a deploy or cache flush, every request misses at once.
Try it
News Feed HLD
Serve a feed that's read thousands of times for every post.