System design deep dive
Design Twitter (Newsfeed): deep dive
Designing Twitter's home timeline is a test of read-heavy fan-out at massive scale: you must deliver new posts to hundreds of millions of feeds in seconds while celebrity accounts with tens of millions of followers threaten to blow up every naive design. This walkthrough gives estimates, APIs, storage, and the hybrid fan-out strategy interviewers expect.
Requirements to pin down first
- Functional: post a tweet (text up to 280 characters, optional media), follow and unfollow, view a home timeline of tweets from followed accounts, view a user's own profile timeline.
- Non-functional: timeline loads in under 200 ms at p99; a new tweet appears in followers' timelines within about 5 seconds; very high availability; eventual consistency is acceptable for timelines.
- Clarify: chronological or ranked timeline, and whether search, trends, and notifications are in scope (usually not in a 45-minute round).
Capacity estimates
| Quantity | Assumption | Result |
|---|---|---|
| Daily active users | 200 million | - |
| Tweets | 0.5 per DAU per day | 100 million/day, about 1,200/s average, 5,000/s peak |
| Timeline reads | 10 refreshes per DAU per day | 2 billion/day, about 23,000/s average, 70,000/s peak |
| Fan-out writes | Average 200 followers per author | 20 billion timeline inserts/day, about 230,000/s |
| Tweet storage | About 300 bytes of text plus metadata | About 30 GB/day, 11 TB/year before replication |
| Timeline cache | 800 tweet IDs at 8 bytes per active user | About 6.4 KB per user, roughly 1.3 TB of Redis across the cluster |
Reads outnumber posts about 20 to 1, and the fan-out multiplies writes by about 200. The design question is where to pay that cost: at write time, at read time, or a mix.
API
POST /api/v1/tweets { text, mediaIds[] } -> { tweetId }
GET /api/v1/timeline/home?cursor= -> { tweets[], nextCursor }
GET /api/v1/users/{id}/tweets?cursor=
POST /api/v1/users/{id}/follow
DELETE /api/v1/users/{id}/followData model
- tweets
(tweet_id PK, author_id, text, media_ids, created_at): sharded bytweet_id, which is a Snowflake ID so it is time-sortable. - user_tweets
(author_id, tweet_id): a per-author index used for profile pages and for pulling celebrity tweets, sharded byauthor_id. - follows
(follower_id, followee_id)stored twice, once keyed by follower and once by followee, so both who do I follow and who follows me are single-partition reads. - home timeline cache: a Redis list per user holding the latest 800 tweet IDs, trimmed on insert.
- media: images and video in object storage, served through a CDN.
How posting and reading work, step by step
- The Tweet service validates the post, assigns a Snowflake ID, writes it to the tweets store, and publishes a
TweetCreatedevent to Kafka. - Fan-out workers consume the event and fetch the author's follower list in pages of a few thousand.
- For a normal author (say under 10,000 followers), workers
LPUSHthe tweet ID into each active follower's Redis timeline andLTRIMit to 800 entries. Inactive users are skipped; their timelines are rebuilt when they return. - For a celebrity author, workers skip the fan-out entirely; the tweet only lands in the author's own
user_tweetsindex. - When a user opens the app, the Timeline service reads their cached list of IDs, then fetches recent tweets from the few celebrities they follow and merges both lists by ID, which sorts by time.
- It hydrates the IDs into full tweets through a tweet cache (author name, text, counts), applies filters such as blocks and deleted tweets, and returns a page with a cursor.
Why hybrid fan-out wins
Pure push means one post from an account with 50 million followers triggers 50 million cache writes, delaying delivery for minutes and spiking load. Pure pull means every timeline read queries hundreds of authors' recent tweets and merges them, which is far too slow at 70,000 reads per second. Hybrid fan-out pushes for the 99%+ of authors with modest audiences and pulls for the small set of celebrities, so each read merges one precomputed list with a handful of celebrity lists. The deeper mechanics of the queue between posting and fan-out are covered in message queues.
Common mistakes in interviews
- Querying
SELECT ... WHERE author_id IN (followees) ORDER BY created_aton every timeline load. - Choosing pure fan-out on write and never addressing celebrity accounts.
- Fanning out full tweet bodies instead of IDs, which multiplies storage and makes edits and deletes painful.
- Ignoring inactive users, who account for a large share of follower lists and waste fan-out work.
- Forgetting pagination with stable cursors; offset pagination breaks when new tweets arrive at the top.
Interview questions
›How do you handle a tweet being deleted after it has been fanned out?
Mark the tweet deleted in the tweets store and tweet cache. Timelines still hold the ID, but hydration skips deleted tweets, so they disappear immediately. A background job can lazily remove the IDs from timelines later.
›What happens when a user follows someone new?
The follow is written to both follow tables immediately. To make the new account's tweets show up, the system can insert that account's last few dozen tweet IDs into the follower's timeline and re-sort, or simply let future tweets arrive through normal fan-out, depending on product expectations.
›How would you switch to a ranked timeline?
Keep the fan-out pipeline as the candidate generator, then add a ranking service that scores a few hundred candidates using features like engagement, author affinity, and recency, and returns the top results. Ranking runs at read time and its features are precomputed offline, so latency stays within budget.
›How do you rebuild the timeline for a user who has not logged in for months?
Their cached timeline was evicted, so on login the Timeline service pulls recent tweets from each followee's user_tweets index, merges the latest 800, and writes them back to Redis. It is slow once, then the user rejoins normal fan-out. Showing a loading state for that first request is acceptable.
›Where is the celebrity threshold set, and is it fixed?
It is a tunable cutoff, often in the range of 10,000 to 100,000 followers, chosen by measuring fan-out cost against read-merge cost. Some systems make it dynamic, for example treating an account as a celebrity only while its follower count or posting rate is high.
