Why reads break first
Writes create data; reads consume it. An Instagram feed load can trigger 100+ reads for one daily post. Tweets, product pages, and YouTube views all share the same imbalance: one write, thousands of readers.
This is the deep dive behind Common patterns. Pair with Database indexing, Caching strategies, Sharding, and Numbers to know.
Indexes · denorm · hardware.
Replicas · shards.
Redis · CDN · TTL.
Hot keys · stampede · versions.
The problem
Open Instagram: dozens of photos, each needing metadata, user info, likes, comment previews — potentially 100+ reads for one session. You might write one photo a day. Amazon product views dwarf uploads; YouTube views dwarf uploads. Read-to-write often starts at 10:1 and climbs to 100:1+.
As reads climb, the primary DB saturates. This is often physics, not a bug you debug away: finite CPU instructions, RAM, disk I/O. Throwing more application code at a saturated disk doesn't help.
Optimize within your database
Before new infrastructure, squeeze headroom from one database: indexing, hardware, denormalization, materialized views.
Indexing
An index is a sorted lookup into rows — like a book index. Without one, the DB does a full table scan (O(n)). With a B-tree (most common), lookups become O(log n). Hash indexes for exact matches; specialized indexes for full-text or geo. Deep dive: Database indexing.
Hardware upgrades
SSD vs HDD (10–100× random I/O), more RAM (working set in memory), more cores. Boring, effective — buys breathing room. Mention it; don't stop there.
Denormalization
Normalized schemas reduce redundancy via joins. Read-heavy paths pay for those joins on every request. Denormalize hot reads: duplicate fields into an order_summary table so one query replaces a multi-table join. Trade write complexity (update many places) for read speed — only when read/write ratio justifies it.
Materialized views
Precompute expensive aggregations (avg product rating) via background jobs instead of on every page load. Refresh on a schedule or on write.
-- Expensive every page load: SELECT p.id, AVG(r.rating) FROM products p JOIN reviews r ON p.id = r.product_id GROUP BY p.id; -- Precompute: CREATE MATERIALIZED VIEW product_ratings AS SELECT p.id, AVG(r.rating) as avg_rating FROM products p JOIN reviews r ON p.id = r.product_id GROUP BY p.id;
Scale the database horizontally
When one server hits limits (~50K–100K read QPS as a rough interview rule of thumb after indexing — see Numbers to know), add servers.
Read replicas
Writes to primary; reads to followers. Bonus: promote a replica on primary failure. Sync replication = consistent but slower writes; async = faster but replication lag (user writes, then reads stale from a lagging replica → read-your-writes from primary for that session).
Sharding for reads
Replicas don't shrink dataset size. Huge tables still scan slowly even when indexed. Sharding splits data: faster per-query, more places to send reads. Mostly a write-scaling tool — prefer caching for many read problems. See Sharding.
Add external caching layers
Access is skewed: viral tweets, popular products get re-read constantly. Caches store hot results in RAM — sub-ms vs tens of ms for DB. Alternatives: more replicas or cache; caches usually win for read-heavy skewed workloads.
Application-level caching
Redis/Memcached between app and DB. Cache-aside: check cache → miss → DB → populate. Celebrity profiles stay hot; inactive profiles expire after TTL.
Invalidation strategies:
- TTL — simple; serve stale until expiry; size from NFRs ("≤30s stale search")
- Write-through / invalidate-on-write — fresher; write latency + careful error handling
- Write-behind — async invalidate; short stale window
- Tagged invalidation — clear related keys by tag
- Versioned keys — bump version; old keys become unreachable
CDN and edge caching
Cache public content at edge PoPs — Tokyo user hits Tokyo edge, not Virginia origin. Can cut origin load 90%+ for product pages, thumbnails, search results. Don't CDN private DMs or account settings (no shared hit rate).
When to use in interviews
Almost every interview ends in scaling talk. For each high-volume API, optimize reads: query plan → replicas → cache → CDN.
Common scenarios
- Bitly — extreme read/write; cache short→long mapping aggressively; CDN for global hits
- Ticketmaster — cache event/venue/charts; not seat availability (oversell risk); replicas for browse, primary for buy
- News feed — precompute active feeds; cache recent posts; paginate (users read first items)
- YouTube — cache metadata; eventually consistent view counts; CDN thumbnails
Common deep dives
Queries slow as the dataset grows?
10K users → snappy; 10M → 30s lookups. Full table scans: find-by-email reads all rows. Add indexes; compound index column order matters ((status, created_at) helps status and status+created, not created alone).
Millions of concurrent reads for one cached key?
Celebrity post: 500K QPS on one key overwhelms one cache shard.
Request coalescing collapses N concurrent misses into one backend fetch per process. Key fanout stores identical copies under feed:star:1..10; clients pick randomly — trade memory and harder invalidation for surviving the herd.
Cache stampede on TTL expiry?
100K QPS homepage; entry expires; all miss at once → DDOS your own DB.
Distributed lock: only first miss rebuilds (timeouts if rebuild fails). Probabilistic early refresh: chance of background refresh rises as TTL nears end — spreads load. Critical keys: refresh every 50 of 60 minutes so they never expire under traffic.
Immediate visibility after updates?
Venue address change can't wait an hour in CDN. Naive delete-on-write races (request between delete and new write caches stale again).
Read version (small cached key) → fetch event:123:v43. Trade-off: two lookups; orphaned versions cleaned by TTL. For feeds/search, use a deleted-items set and filter on read while background-invalidating large structures. Match consistency to data: profiles tolerate 5 min; venues may need immediate.
In your interview
"Reads dominate — I'll scale the read path in order: indexes on filter/join/sort columns, denormalize only hot paths, read replicas with read-your-writes for the session, then Redis cache-aside with TTL sized from staleness NFRs plus invalidate-on-write for critical keys, CDN for public assets. Hot keys get coalescing or fanout; TTL cliffs get early refresh. I won't draw Redis before I can argue hit rate and invalidation."
Read path Fermi drill
Cost and performance levers
Interview Q&A by level
Practice saying these out loud for scaling reads. Interviewers grade clarity and judgment more than buzzwords.
Match depth to the bar: define → trade off → operate. Don't dump principal answers in an entry-level screen.
Wrapping up
Read scaling is the most common interview scaling challenge. Read traffic grows faster than writes; physics eventually wins. Optimize in-DB first — modern databases handle more than candidates assume when indexed — then replicas, then caches. Know performance wins and operational cost of each rung.
Continue with Common patterns, Database indexing, Caching strategies, Sharding, Redis, Design Gopuff, Design Ticketmaster, and Numbers to know.