Course Content
System Design Interview
31 sections · 71 lessons
News Feed: scope, scale and the fan-out trade-off
The prompt: "Design a news feed."
Set a 45-minute timer and attempt it before reading. This is one of the two or three most-asked system design questions in the industry, and the version of it you produce under time pressure — not the version you read — is the one you will be able to reproduce in an interview.
This lesson gets you from the prompt to the central decision. It scopes the feed with five questions, runs the estimate that makes the decision for you, and then costs the two ways of delivering one post to many readers. By the end you will know why neither of them works alone.
What a news feed is
The five questions
1. Chronological or ranked? Chronological means newest first, and the feed is a merge of sorted lists. Ranked means a model scores each candidate post for this viewer. That difference decides how much of the feed can be precomputed, which is the central question of the design. Scope it as chronological first, then discuss ranking as an extension — Ranking and follow-ups does exactly that.
2. Is the graph symmetric or asymmetric? Friends (both parties agree, capped at a few thousand) behave very differently from followers (one-directional, uncapped). Ask for the maximum: "is there an account with 100 million followers?" If yes, you have the celebrity problem, and the whole design turns on it.
3. What media types? Text, images, video. Media never travels through the feed pipeline — it lives in blob storage behind a content delivery network, and the feed carries an identifier. Say that early so it stops being a distraction.
4. How fresh must the feed be? "A post appears within a few seconds for most followers" is a normal answer and a demanding one. "Within a minute" makes several designs viable that otherwise are not.
5. Feed of what, exactly? Posts only, or also likes, comments, follows, and recommendations? Every extra source multiplies the merge work at read time.
Scope it out loud
Exclude: ranking model training, ads insertion, spam and integrity filtering, and stories. Include: publish, fan-out, feed read with pagination, and the caching layout. That is comfortably 45 minutes of material.
Requirements and scale
The estimate is not a ritual here. The fan-out decision later in this lesson is made by these numbers, and a candidate who skips them ends up asserting a preference instead of reaching a conclusion.
Functional and non-functional
Functional: publish a post; read a feed page of 20 posts; paginate backwards; see new posts appear without a full reload.
Non-functional: feed read at the 99th percentile under 200 ms, because the feed is the app's first screen; publish acknowledged in under 500 ms, with delivery to followers allowed to lag; high availability, and eventual consistency is acceptable — a post arriving a few seconds late in one follower's feed is not a failure (Consistency models).
The numbers
Invented but plausible figures for a large social product. A day is 100,000 seconds (Rounding aggressively and staying fast).
| Quantity | Assumption | Result |
|---|---|---|
| Daily active users | 300 million | — |
| Posts per user per day | 0.5 | 150M posts/day |
| Average post write rate | 150M ÷ 100,000 | 1,500 posts/s |
| Peak post write rate | 3× average | 4,500 posts/s |
| Feed opens per user per day | 10 | 3B feed reads/day |
| Average feed read rate | 3B ÷ 100,000 | 30,000 reads/s |
| Peak feed read rate | 3× average | 90,000 reads/s |
The read-to-write ratio is 3,000,000,000 ÷ 150,000,000 = 20:1. Feeds are read-heavy, but not as lopsidedly as a URL shortener at 100:1 (Section 10). Twenty to one is the ratio that makes the hybrid sensible rather than obvious.
Storage
A post row — identifier, author, timestamp, text, media references, counters — averages about 1 KB.
150M posts/day × 1 KB = 150 GB/day = 55 TB/year of post metadata.
Media is separate and far larger, but it goes to blob storage and a content delivery network and does not touch this pipeline.
The number that decides the design
Follower counts are extremely skewed. Assume an average of 200 followers per account:
150M posts/day × 200 followers = 30 billion feed insertions per day
30,000,000,000 ÷ 100,000 s = 300,000 feed writes per second average
At 3× peak: 900,000 feed writes per second
That single line is the problem. Writing 900,000 rows per second is a large but buildable system. The problem is the distribution behind the average.
Fan-out on write versus fan-out on read
This is the central trade-off of the section and the one new idea it owns. Everything else in the design is assembly.
Fan-out on write, costed
Publishing a post is followed by an asynchronous job that inserts the post identifier into each follower's feed list.
- Write cost: 30 billion insertions/day, 300,000/s average and 900,000/s peak, from the estimate above.
- Read cost: one range read of a precomputed list. At 90,000 peak reads/s against an in-memory feed cache, each read is a single lookup returning 20 identifiers — under a millisecond of store time.
- Storage: each user's feed holds, say, 200 identifiers. 300M users × 200 × 16 bytes (an 8-byte post identifier plus an 8-byte sort score) = 960 GB. Fits across a modest in-memory cluster.
Where it breaks. An account with 100 million followers posts once. That is 100 million insertions from one action. If the fan-out tier sustains 100,000 insertions per second for that job, the last follower gets the post
100,000,000 ÷ 100,000 = 1,000 seconds ≈ 17 minutes
after it was published. On a live broadcast, 17 minutes is not a lag, it is a different product. And ten such accounts posting inside a minute produce a billion insertions that starve everyone else's fan-out.
Fan-out on read, costed
Nothing happens at publish time beyond storing the post.
- Write cost: 1,500 post inserts/s. Trivial.
- Read cost: for each feed request, fetch the following list (average 200 accounts), fetch each author's recent posts, merge, take the top 20. That is 200 lookups per feed read. At 30,000 reads/s: 30,000 × 200 = 6 million lookups per second, and at peak, 18 million.
- Latency: those 200 lookups are issued in parallel across many shards, so the response waits for the slowest of 200. If a single lookup has a 99th-percentile latency of 20 ms, the probability that all 200 come back fast is 0.99²⁰⁰ ≈ 13%. In other words, roughly seven feed reads in eight hit at least one slow shard. This is tail amplification, and it is the reason pull-only feeds feel sluggish.
Where it wins. The celebrity case costs nothing extra. One post, one row, and every reader picks it up on their next read.
The comparison
| Fan-out on write | Fan-out on read | |
|---|---|---|
| Work at publish | 30B insertions/day | 150M inserts/day |
| Work at read | 1 lookup | ~200 lookups |
| Feed read latency | Under 10 ms | 100 ms+, tail-dominated |
| Celebrity post | 17 minutes to the last follower | Free |
| Wasted work | Feeds built for users who never log in | None |
| Storage | ~1 TB of feed lists | None beyond posts |