Design Twitter
The classic "design a news feed" problem, and one of the most-asked system design questions specifically because its core tension — how a feed actually gets assembled — is a direct, concrete instance of the Push vs. Pull Architecture tradeoff, applied at a scale where the "obvious" answer breaks. Following the framework from How to Answer a System Design Interview Question.
1. Requirements
Functional:
- Users post short text posts ("tweets") and follow other users.
- A user's home timeline shows recent posts from everyone they follow, roughly in reverse chronological order.
Non-functional:
- Reads (viewing a timeline) vastly outnumber writes (posting) — this is an extreme version of the read-heavy pattern already seen in Caching 101.
- Timeline generation must be fast — users expect a feed to load near-instantly, not compute in real time on every request.
- Eventual consistency is fine: a new post appearing in a follower's feed a few seconds late is unnoticeable.
Scale estimate: assume 300M users, an average of 200 follows per user, and 5,000 posts/sec at peak. The follow relationship's fan-out — one post potentially needing to reach hundreds or millions of followers — is the number that actually drives this design, not the raw post-write volume.
2. API Design
POST /tweets body: { author_id, text } returns: { tweet_id }
GET /timeline/{user_id} returns: [{ tweet_id, author_id, text, posted_at }]
POST /follows body: { follower_id, followee_id }
3. Data Model
tweets
tweet_id VARCHAR PRIMARY KEY
author_id VARCHAR
text VARCHAR(280)
posted_at TIMESTAMP
follows
follower_id VARCHAR
followee_id VARCHAR
PRIMARY KEY (follower_id, followee_id)
timelines (precomputed, per user)
user_id VARCHAR
tweet_ids LIST -- ordered, most recent first
The timelines table is the design's central decision made concrete: rather than computing a user's feed at read time by querying every followee's tweets and merging them, a precomputed list is maintained per user — the mechanism the deep dive below explains.
4. High-Level Design
5. Deep Dive: fan-out on write vs. fan-out on read
This is the entire design in one question: when a user posts, do you push that post into every follower's precomputed timeline right away (fan-out on write), or leave it where it was written and merge-query every followee's posts only when a follower actually asks for their timeline (fan-out on read)?
- Fan-out on write (push) — on every post, insert its ID into every follower's precomputed timeline cache immediately. Reads become nearly free — just fetch the already-assembled list — which fits the extreme read-heavy access pattern from the scale estimate almost perfectly. The cost lands entirely on the write path instead: a user with 10 million followers turns one post into 10 million writes.
- Fan-out on read (pull) — store the post once, and assemble a requester's timeline on demand by querying and merging all their followees' recent posts. Writes stay cheap and constant-cost regardless of follower count, but every single timeline read now does real, potentially expensive work merging many sources.
Real systems use both at once, split by exactly the case that breaks each approach: fan-out on write for ordinary users (most accounts have a follower count small enough that pushing to all of them is cheap), and fan-out on read specifically for celebrity accounts with millions of followers, merging their posts into a requester's timeline at read time instead of paying for tens of millions of writes per post. This hybrid is the practical answer to what's often called the "celebrity problem," and naming it explicitly — rather than picking one strategy uniformly — is the strongest possible answer here.
6. Deep Dive: merging two sorted sources into one correctly ordered feed
The hybrid design above quietly introduces a new problem: a requester's final timeline is now assembled from two different sources — their precomputed timeline (already has every ordinary follow's posts, in order) and a live query against just their celebrity follows (a handful of accounts, so this query stays cheap). Both are correct on their own; the feed still has to present them as one single, correctly time-ordered list.
The key fact that makes this cheap is that both inputs already arrive pre-sorted by timestamp — the precomputed timeline was built that way, and the live celebrity query can ORDER BY posted_at on a small result set trivially. Combining two already-sorted lists into one sorted list doesn't require re-sorting anything; it's the same merge step from merge sort: walk both lists with a pointer each, repeatedly taking whichever front item is newer, until one list is exhausted. That's an O(n) merge instead of an O(n log n) sort, and it's exactly why the celebrity-follow query stays deliberately small (a few accounts, not "everyone this user follows") — the merge only stays cheap if the second input does too.
7. Tradeoffs
The hybrid split directly trades a small amount of read-path complexity (merging two sources for some users' timelines) for avoiding the worst-case cost of either pure strategy: pure fan-out-on-write would make a celebrity's post catastrophically expensive to write; pure fan-out-on-read would make every single timeline read expensive, even though the overwhelming majority of users don't follow anyone with an extreme follower count.
It's also worth being explicit about what this design deliberately leaves out: the requirements above scope the timeline to strict reverse-chronological order, but a real product's feed is usually ranked, not purely chronological — promoted posts, "you might like this" suggestions, and relevance scoring all reorder the merged result after retrieval. That's a genuinely separate concern from fan-out (it's a scoring/ranking problem layered on top of an already-assembled feed, not a storage or fan-out decision), which is exactly why it's worth naming as out of scope rather than silently ignoring it — an interviewer who cares about ranking will ask, and "that's a separate ranking pass after this merge, out of scope for what was asked" is a stronger answer than not having considered it at all.
Fan-out on write vs. fan-out on read: pros and cons
Fan-out on write
- Timeline reads are nearly free — just fetch an already-assembled list
- Read latency stays flat and predictable regardless of how many people someone follows
- Matches an extremely read-heavy access pattern almost perfectly
Fan-out on read
- Every timeline read does real work merging many followees' posts on the spot
- Read latency grows with how many people a user follows
- Harder to keep read latency predictable and low under load
Further Reading
- Twitter Engineering — Timelines at Scale — Twitter's own account of the fan-out and celebrity-problem tradeoffs this design is based on.
- System Design Primer — Design a news feed system — a widely referenced walkthrough of the same fan-out tradeoff.
Saved locally in your browser — visible in the sidebar as you go.