System design · Fan-out and the celebrity problem

How to design Twitter's home timeline

Designing a social feed - Twitter's home timeline, Instagram's feed, Facebook's News Feed - is the canonical mid-level system design interview. The whole question turns on one trade-off, fan-out on write versus fan-out on read, and one edge case that breaks the naive answer: the account with tens of millions of followers.

Updated · 5 min read

Run it: click through the fixes and watch the numbers change

Live simulationFailing
no cacheUsers5,000 req/sAPI Server×65,000 req/scapacity 6,000 req/sDatabase×45,000 req/sreads 3,000 · writes 1,000 req/s
p99 latency
614ms
Errors
39.0%
Cost
$1,101/mo

The database's 3 read replicas can serve 3,000 reads/s but are receiving 4,950. 39% of requests fail. A cache in front of it would absorb most of those reads.

Real simulator engine, not an animation.Edit in the playgroundBuild a social feed in the simulator
Embed this simulation in your blog, docs or course

Free to embed. Paste this HTML anywhere that accepts an iframe.

Requirements

  • Functional: post a tweet; follow and unfollow accounts; read a home timeline of recent tweets from accounts you follow, newest first.
  • Non-functional: timeline reads must be fast (a few hundred milliseconds end to end) and highly available.
  • Non-functional: a new tweet may take a few seconds to appear in followers' timelines - eventual consistency is acceptable, which is the assumption that makes the whole design possible.
  • Out of scope unless asked: ranking, ads, search, notifications.

Capacity estimates

QuantityAssumptionResult
Daily active users200 million-
Tweets posted1 tweet per user per day≈ 2,300 tweets/s average
Timeline reads50 timeline loads per user per day≈ 115,000 reads/s average
Average fan-out200 followers per tweet≈ 460,000 timeline inserts/s
Timeline cache800 tweet IDs × 8 bytes per active user≈ 1.3 TB of memory

Reads outnumber posts by roughly 50 to 1, and the fan-out multiplies every post by the follower count. Both facts push you towards precomputing timelines so that reads are cheap.

API design

POST /api/tweets            { "text": "..." }   → 201 { "id": "1850..." }
POST /api/follows           { "followee_id": 42 } → 204
GET  /api/timeline?cursor=…  → 200 { "tweets": [...], "next_cursor": "…" }

Paginate the timeline with a cursor (the last tweet ID you saw), not a page number. New tweets arrive constantly, and offset pagination would skip or repeat them.

Data model

  • tweets: tweet_id (time-sortable, Snowflake-style), author_id, text, created_at. Store in a wide-column or sharded relational store, sharded by tweet_id.
  • follows: follower_id, followee_id, with indexes in both directions - who I follow, and who follows me.
  • home timelines: per user, a list of the most recent tweet IDs from accounts they follow, kept in an in-memory store such as Redis.

Fan-out on write vs fan-out on read

This is the core decision. Say both options and their costs before choosing.

Fan-out on write (push)Fan-out on read (pull)
On postInsert the tweet ID into every follower's cached timelineWrite the tweet once
On readRead one precomputed list - fastFetch recent tweets from every followee and merge - slow
CostWrites multiply by follower countReads multiply by followee count
Breaks whenAn account has millions of followersUsers follow thousands of accounts, or reads spike

Because reads dominate, fan-out on write is the right default: pay once when a tweet is posted so that thousands of reads are cheap.

The celebrity problem

Fan-out on write assumes follower counts are small. When an account with 50 million followers posts, one tweet becomes 50 million timeline inserts. The fan-out workers fall behind, every other user's tweets queue up behind the celebrity's, and freshness collapses for everyone.

The read side has its own version: when a celebrity tweets, millions of people refresh at once. In the simulation above, a 3× read spike overwhelms the API tier even though the timeline cache protects the database - a reminder that the bottleneck moves as soon as you fix the first one.

The hybrid design

Production feeds combine both strategies. Twitter described this approach in its 2013 "Timelines at Scale" talk: home timelines are precomputed lists of tweet IDs held in Redis, built by fan-out on write, while tweets from very high-follower accounts are merged in at read time.

  • Normal accounts: fan-out on write into followers' cached timelines, through a queue drained by fan-out workers, so bursts become backlog instead of errors.
  • High-follower accounts: skip fan-out; at read time, fetch their recent tweets and merge them into the cached list.
  • Inactive users: don't maintain their timelines at all; rebuild on their next visit.
  • Cap each cached timeline (for example 800 IDs). Older history is fetched from storage on demand.

Reading a timeline

A timeline request reads the user's list of tweet IDs from the cache, merges in recent tweets from the high-follower accounts they follow, then hydrates the IDs into full tweets with a batch lookup - itself served mostly from a tweet cache. Every step on the hot path is an in-memory read.

What interviewers look for

  • You estimated the read-to-write ratio and the fan-out multiplier before designing.
  • You explained both fan-out strategies and chose one with a reason.
  • You raised the celebrity problem yourself and solved it with the hybrid.
  • You used a queue to absorb fan-out bursts and cursor pagination for reads.
  • You stated that the timeline is eventually consistent and why that is acceptable.

Frequently asked questions

What is the celebrity problem in system design?

+

With fan-out on write, a post is copied into every follower's timeline. For an account with millions of followers, one post becomes millions of writes, which overwhelms the write path and delays everyone else's posts. The standard fix is a hybrid: fan out normally for most accounts and merge high-follower accounts' posts in at read time.

Is fan-out on write or fan-out on read better?

+

Fan-out on write makes reads fast at the cost of expensive writes, which suits read-heavy feeds. Fan-out on read makes writes cheap but timeline reads slow. Large feeds use a hybrid that switches strategy based on follower count.

Where is the timeline stored?

+

As a precomputed list of tweet IDs per user in an in-memory store such as Redis. The tweets themselves live in a separate store, and the timeline is hydrated from IDs into full tweets at read time.

How do you paginate a news feed?

+

With a cursor - usually the ID of the last item returned - rather than a page number. Because new items arrive continuously, offset pagination would skip or repeat items as the feed shifts.

Does a news feed need strong consistency?

+

No. It is acceptable for a new post to take a few seconds to appear in followers' feeds. Accepting eventual consistency is what allows timelines to be precomputed asynchronously.

Now break one yourself.

The first challenge takes about two minutes. No signup.