Why a news feed is a classic design question, and what it teaches
A news feed shows each user a ranked list of recent posts from the accounts they follow. It looks simple, but one post may have to reach millions of followers while millions of people open their feed at once. It teaches fan-out, caching, hot keys and the cost of precomputing.
Fan-out means delivering one post to many followers' feeds. A hot key is a single account or item that receives far more traffic than the rest, such as a celebrity's post. Precomputing means building each feed ahead of time, when a post is written, instead of when it is read.
It gives you two things interviewers always ask about:
- Low read latency: opening the feed should be fast, because people open it far more often than they post.
- Scalability: one post by an account with a huge audience must not melt the system.
Requirements to confirm first:
- Functional: publish a post, follow and unfollow, read your feed in order, optionally ranking and media.
- Non-functional: feed opens in a fraction of a second, new posts show up quickly, millions of users, and a few accounts with a huge number of followers.
Skip the design, or simplify it, when:
- Users follow few accounts and posts are rare: query the posts of everyone you follow at read time.
- The feed is the same for everyone (a public timeline): cache one list.
Capacity estimation (illustrative numbers)
Estimates decide the design, so do them before choosing a strategy. These figures are assumptions for practice, not measurements of any real product.
- Reads: 100 million daily active users, each opening the feed 10 times a day, is 1,000,000,000 opens a day. A day has 86,400 seconds, so that is about 11,600 opens a second on average, and about 35,000 a second at a peak of three times the average.
- Writes: if 10 percent of those users post once a day, that is 10,000,000 posts a day, about 116 a second. Reads outnumber posts 100 to 1.
- Push cost: with an average of 200 followers, 10,000,000 posts cause 2,000,000,000 cache writes a day, about 23,000 a second.
- Pull cost: if each reader follows 200 accounts, 1,000,000,000 opens cause 200,000,000,000 post lookups a day, about 2,300,000 a second. That is 100 times the push cost, which is why push wins for ordinary accounts.
- A celebrity: one post to 20,000,000 followers is 20,000,000 cache writes. If the worker pool can do 100,000 cache writes a second, the last follower sees the post after about 200 seconds.
- Cache size: 500 post IDs per user at about 16 bytes each (an ID and a score) for 100,000,000 users is 800,000,000,000 bytes, about 800 GB before replication and overhead. Caching only active users and trimming the list shrinks it.
Try it
One author posts and followers open the feed. Switch the strategy, then change who posts or how often the feed is read.
News Feed
Step 1 of 4 · Press Space to play, arrow keys to stepInitial state. One author with 1000 followers is about to post. After that, followers open their feed 10 times in total.
- tick:
- 0
- feed writes:
- 0
- read queries:
- 0
- total work:
- 0
1 tick = one step of the simulation.
Things to try:
- Run Fan-out on write for a normal user. Copying a post to 50 caches is cheap, and reading is one cache lookup.
- Run the same strategy for a celebrity. One post causes a thousand writes.
- Run Fan-out on read with 200 feed opens, then try the Hybrid and compare total work.
What to watch for: total work adds feed writes and read queries, counting each as one unit. That is a simplification, because a write is usually dearer than a read.
- Normal user: push costs 50 + 10 = 60, pull costs 2000, and the hybrid pushes, so it also costs 60.
- Celebrity: push costs 1000 + 10 = 1010, pull costs 2000, and the hybrid costs 20. Pull is not cheap here either, because each simulated reader follows 200 accounts and pull checks all 200 on every open. The hybrid wins by pulling only the one celebrity, so its figure assumes the reader follows a single celebrity.
- 200 feed opens: push costs 50 + 200 = 250, pull costs 40000, and the hybrid pushes at 250.
Feed generation strategies
| Strategy | How it works | Good when | Weakness |
|---|---|---|---|
| Fan-out on write (push) | When someone posts, copy the post ID into every follower's feed cache | Most users, followers in the hundreds | A celebrity post causes millions of writes, and inactive users' caches are wasted |
| Fan-out on read (pull) | Store the post once. At read time fetch recent posts from everyone you follow and merge them | Readers who follow few accounts, or users who rarely open the feed | Every feed open is expensive and slow |
| Hybrid | Push for normal accounts, pull for celebrities and merge at read time | Real systems with both kinds of accounts | More code, and a rule for who counts as a celebrity |
Push vs pull
- Push moves the cost to write time. Reads are one cache lookup, but a post by a popular account is amplified into a huge number of writes, and followers see it only after the fan-out finishes.
- Pull moves the cost to read time. Writes are one insert, but each feed open touches many accounts, which is slow when readers outnumber posters.
Reads usually outnumber writes by a large factor, so push wins for ordinary accounts and pull wins for the few accounts that would explode the push.
Each side scales with a different number. Push cost grows with the author's followers. Pull cost grows with the accounts each reader follows, multiplied by the number of feed opens. Push is cheaper for a post when followers are fewer than about (accounts followed minus 1) times the number of opens. With 200 accounts followed and 10 opens that is 1,990 followers, so a 1,000-follower account is still cheaper to push in this model. The celebrity threshold is therefore a tuned setting, not a fixed law.
How a hybrid feed works
- A user posts. The post is saved in the post store, and an event goes to a queue.
- A fan-out worker reads the author's follower list. If the author has fewer than a threshold of followers, it adds the post ID to each follower's feed cache (a short list of recent IDs).
- For celebrity authors, the worker does nothing.
- When a user opens the feed, the service reads their cache, fetches recent posts from the celebrities they follow, merges and ranks the lists, and loads post details by ID.
- Caches keep only the latest few hundred IDs, and inactive users' caches expire and are rebuilt on demand.
Details that matter in practice:
- Which followed accounts are celebrities? Step 4 needs this cheaply, so keep a flag on the account, or a small per-user list of followed celebrities, instead of scanning all follows on every open.
- Follow and unfollow: when a user follows someone, backfill that author's recent post IDs into their cache. When they unfollow, remove that author's IDs, or filter them out at read time.
- Delete and edit: posts are stored once and feeds hold IDs only, so an edit shows at once. Deleted posts are filtered out when details are loaded.
- Threshold boundary: an account that crosses the threshold changes from push to pull. Old pushed IDs stay valid, and new posts are merged at read time.
- Pagination: return a cursor (the last score seen) with each page, so the next page is the next slice of the sorted list.
News feed design vs the alternatives
| Concern | Hybrid feed service | Pure pull from the database | Chronological per-author pages |
|---|---|---|---|
| Fast feed open | Yes | Slow for many follows | Slow to merge |
| Handles a celebrity post | Yes | Yes | Yes |
| Cost of a normal post | Some writes | One write | One write |
| Ranking and mixing sources | Yes | Hard | No |
| Extra moving parts | Queue, workers, caches | None | None |
| Best for | Large social products | Small products | Simple blogs |
Choose pure pull while the product is small, and move to the hybrid when read latency or celebrity posts hurt.
Avoiding a new single point of failure
- Feed caches: they are derived data, so if one is lost it is rebuilt from the post store and the follow graph.
- Fan-out workers: run many behind a queue. If they fall behind, new posts appear late but are not lost.
- Post store: replicate it and partition by author or post ID. Partitioning by author puts a celebrity's posts on one partition that every read merge hits, so cache those recent posts or partition by post ID.
You accept that feeds are eventually consistent: a new post may take a few seconds to reach every follower.
More failure cases to walk through:
- Queue backlog: fan-out delay is roughly the followers of the author divided by the workers' write speed (about 200 seconds in the estimate above). Add workers, split a huge job into batches of followers, and alert on queue age.
- Worker crash and retry: a job may run twice. Adding the same post ID with the same score to a sorted set again changes nothing, so retries are safe.
- Feed cache lost: serve the feed by pulling for that user, then rebuild the cache. Reads are slower for a while but correct.
- Ranking service down: fall back to newest first, so the feed still opens.
Common mistakes
- Pushing celebrity posts to everyone. Use pull or a hybrid for large accounts.
- Storing full posts in every feed. Store IDs only and load details separately.
- Unbounded feed caches. Keep only the most recent entries.
- Fan-out in the request path. Do it asynchronously from a queue.
- Ignoring inactive users. Skip pushing to users who have not opened the app for a long time.
- Hard-coding a celebrity threshold. Make it a setting you can tune.
How to talk about a news feed in an interview
- Ask for the scale: followers per account, posts per day, feed opens per day, and whether the feed is ranked.
- Explain push vs pull with the read to write ratio, and say why celebrities break pure push.
- Propose the hybrid, with a queue, fan-out workers and per-user feed caches holding IDs.
- Name the trade-off: precomputing makes reads fast but adds write cost and storage, and gives eventual consistency.