Design a social news feed (Twitter / Facebook)
A timeline for 500 million users where a celebrity post reaches 50 million followers.
- Fan-out on write versus fan-out on read — Pushing a post to every follower's inbox, or assembling the feed when asked.
- Caching strategies — Read-through, write-through, write-back, TTLs and invalidation.
- Sharding and partitioning — Splitting data by key so each machine holds a slice it can handle.
- Message queues and pub/sub — Decoupling producers from consumers with a durable log in between.
- Ranking pipelines — Scoring thousands of candidates in stages, cheap first, expensive last.
01The design, in the six-step framework
1. Requirements
Functional
- A user follows others and sees a feed of their recent posts (text, images, links) in reverse chronological order or ranked.
- Posting is fast and a post appears in followers' feeds within seconds.
- Likes, comments and reposts are shown with counts; a user can page back through a long history.
- Out of scope: search, direct messages, the ranking model's internals, ads.
Non-functional
- 500 million daily users; 100 million posts a day; a user follows 300 accounts on average; some accounts have 50 million followers.
- Feed load under 200 ms at p99; posting under 500 ms; fan-out to most followers within 5 s.
- Read-heavy: each user opens the feed 10 times a day → 5 billion feed loads a day.
- Availability 99.99 percent; a post is never lost once acknowledged; a feed may be briefly stale but never shows a post twice or out of order.
Feed loads: 5 × 109 / 86,400 ≈ 58,000/s average, 200,000/s at peak. Posts: 108 / 86,400 ≈ 1,200/s average, 5,000/s at peak.
Fan-out on write: 108 posts × 300 followers average = 3 × 1010 inbox inserts a day ≈ 350,000/s, about 1.5 million/s at peak. Each inbox entry is 16 bytes (post id, time); 3 × 1010 × 16 B = 480 GB/day of inbox writes, kept for a few days in memory.
The celebrity problem: one post by an account with 5 × 107 followers is 5 × 107 inserts, 40 times a normal second's whole fan-out, which is why celebrities get a different path.
2. Core entities
- User: id, profile, follower count, is_celebrity flag (followers above a threshold).
- Follow: follower id, followee id, since.
- Post: id (time-ordered), author, text, media ids, created-at, visibility.
- Feed inbox: user id → list of (post id, score or time), capped at the last few hundred entries.
- Engagement: post id → counts (likes, comments, reposts), plus per-user like records.
3. API
POST /postsbody: text, media ids → post id; returns as soon as the post is durable, before fan-out.GET /feed?cursor=&limit=20→ hydrated posts in order with a cursor (the last post id or score seen).POST /users/{id}/follow,DELETE→ changes the follow graph and schedules a feed adjustment.POST /posts/{id}/like→ idempotent per (user, post).
4. High-level design
Posting and reading:
- The post service writes the post to the post store and publishes an event; the client gets its post id back in tens of milliseconds.
- Fan-out workers read the author's follower list and insert the post id into each follower's inbox (a capped list in memory), unless the author is a celebrity.
- A feed read takes the user's inbox (a few hundred post ids), merges in recent posts from the celebrities the user follows (fetched on read), ranks or sorts, and hydrates the top 20 from the post store and the engagement counters through a cache. Media is served by the CDN.
5. Deep dives
Fan-out on write, fan-out on read, or both?
| Write cost | Read cost | Latency to appear | Where it breaks | |
|---|---|---|---|---|
| Fan-out on write (push) | one insert per follower | one inbox read | seconds | celebrities: 50 million inserts per post |
| Fan-out on read (pull) | none | read 300 followees' recent posts and merge | immediate | feed load does 300 reads under 200 ms |
| Hybrid | push for normal authors | pull only the few celebrities | seconds, or immediate for celebrities | threshold tuning |
Choice: hybrid. Push gives cheap, fast reads for the common case; pull for accounts above a follower threshold (say 1 million) caps the write amplification at a bounded number of inserts per post. A user follows few celebrities, so the read-side merge touches a handful of recent-post lists, each small and heavily cached. Inactive users are the other optimisation: do not push to inboxes of users who have not opened the app in a month; rebuild their feed on return by pulling.
How do we hit 200 ms when a feed load touches inboxes, the graph, posts and counters?
Keep inboxes in memory, sharded by user id, as capped lists of post ids, so the first read is a single key fetch. Hydration is the expensive part: 20 posts, 20 authors, 20 sets of counters. Batch every lookup (one multi-get per store), serve posts and author profiles from a cache with a high hit rate (recent posts are what everyone reads), and keep engagement counters in a counter cache that is updated asynchronously (see counters). Pagination uses a cursor on (score, post id), never offsets, so a new post arriving mid-scroll does not duplicate or skip an item. Ranking runs on the few hundred candidates in the inbox with a model that takes a few milliseconds; a heavier model runs only on the first page.
Consistency: what does "never twice, never out of order" require?
Inbox inserts are idempotent on (user, post id), so a retried fan-out job cannot duplicate. Post ids are time-ordered, which gives chronological order without timestamps from many clocks. A follow or unfollow is an edge change plus an asynchronous inbox fix: unfollow removes that author's recent ids from the inbox (or the feed service filters them at read time until the fix lands), follow backfills a few recent posts. Deleting a post leaves stale ids in millions of inboxes; the feed service drops ids whose hydration fails, which is cheaper than chasing every inbox. All of this is eventual, which is fine; the hard invariant is on the post store, where a post acknowledged to its author is durable.
The celebrity post: a worked case
An account with 50 million followers posts. No fan-out happens. Instead the post lands in the author's recent-posts list, which is replicated into caches in every region. Each follower's next feed load pulls that list (one cached read), merges it with the inbox, and ranks. The cost moves from 50 million writes at post time to one small read per feed load by followers, spread over the following hours, and most of those reads are cache hits. The interviewer's follow-up is a user who follows 5,000 celebrities; cap the pull set at the most engaged few dozen and push the rest, which is why the threshold is a per-pair decision in mature systems rather than a global flag.
Sizing the inbox tier and surviving its loss
Keeping the last 500 post ids for 500 million users at 16 bytes each is 4 TB of memory, held on a few dozen large machines and replicated once; adding a time-based eviction keeps inactive users out of memory altogether. Because the inbox is a derived view, losing a shard is not data loss: the feed service falls back to pull mode for affected users (read followees' recent posts and merge) while a rebuild job regenerates inboxes from the post store and the follow graph. That fallback is slower, so it is rate limited and prioritised for active users, and it is the same code path used for users returning after a long absence.
6. What a strong answer sounds like
- Give the fan-out arithmetic and let it force the hybrid design; name the celebrity threshold.
- Draw the read path as inbox fetch, merge, rank, hydrate, with batching and caches at each hop.
- State the idempotency and ordering invariants and what is only eventual.
- Say that the post store, not the inbox, is the source of truth; inboxes can be rebuilt.
- Expect follow-ups on ranking features, on the follow graph for high-fan-in users, on media upload and the CDN, and on deleting a post.
- Common mistake: pure pull with a join over followees on every feed load, or pure push with no plan for celebrities.
02Where this question was reported
- IGotAnOffer · SWE: 'Design Twitter', 'Design a social network'; mid-level: newsfeed
- IGotAnOffer · 'How would you design a social network?'
- IGotAnOffer · 'read-heavy social network like Facebook'
- interviewkickstart.com · 'social media with messaging board like Quora or Reddit'; 'your version of Facebook/Twitter'
- DesignGurus · 'Social Media Feed System'
- Educative · 'newsfeed system'
- scaleengineer.com · Round 2: 'news feed system for a social media platform'; 'design Twitter' cited
- System Design Handbook · 'a feed' as L5 question type
- LeetCode Discuss · Additional round: TikTok-style Google News; reached ideal solution in 30 min (search snippet)
- Blind · Google News; interviewer not interested in scale but in ranking and relevancy strategy
- LeetCode Discuss · Very vague prompt related to news generation with scattered requirements; No Hire for not discussing multiple approaches (search snippet)
- 1point3acres · Onsite included a news feed design plus an EC2-metrics design (search snippet)