A microblogging service where users post short messages (tweets) and see a timeline of tweets from accounts they follow.
Functional
- Post a tweet.
- Follow and unfollow users.
- View a home timeline of recent tweets from followed accounts.
Non-functional
- Very read-heavy.
- Low-latency timeline.
- Eventual consistency is fine for the timeline.
Assume 200 million daily active users and 100 million tweets per day. Timeline reads vastly outnumber writes. Tweets are small (text), so the challenge is fan-out and timeline assembly, not raw storage.
See the estimation cheat sheet.
POST /tweetswith the text.GET /timelinereturns a page of the home timeline.POST /followandDELETE /follow.
- Users, Tweets, and a Follows graph.
- Tweets are partitioned by tweet id or user id. The home timeline is often a precomputed list of tweet ids per user, held in a fast store.
This is the same fan-out problem as a social feed:
| Approach | How | Best for |
|---|---|---|
| Fan-out on write (push) | Insert the tweet id into each follower's timeline | Normal users; fast reads |
| Fan-out on read (pull) | Assemble the timeline at read time | High-follower accounts |
| Hybrid | Push for most, pull for the few with huge followings | The realistic answer |
The hybrid model avoids the write storm when a user with tens of millions of followers tweets.
- Timeline cache: precomputed timelines in memory for fast reads (see caching).
- Sharding: partition tweets and timelines by user id (see sharding).
- Merging: at read time, merge pushed timelines with pulled tweets from high-follower accounts, sorted by time.
- The high-follower fan-out problem, solved by the hybrid model.
- Write amplification of push vs read cost of pull; the hybrid balances them.
- Read scaling via caching and replication.
flowchart LR
Client --> App[App Servers]
App --> TL[Timeline Service]
App --> Tweets[(Tweets: sharded)]
TL --> Cache[(Timeline Cache)]
- Practice live: Mock interviews
- Full course: Grokking the System Design Interview