Fan-Out on Write vs Fan-Out on Read (and Fan-Out/Fan-In)
Fan-out on write vs fan-out on read for timelines, Twitter's hybrid for celebrities, and the general fan-out/fan-in pattern for search, feeds and notifications.
Fan-out means turning one action into many: one post written into many followers' feeds, one query sent to many shards, one notification sent to millions of devices. Fan-in gathers the many results back into one. This page covers the famous timeline version (fan-out on write vs fan-out on read, and Twitter's hybrid) and the general fan-out/fan-in pattern used by search, feeds and notifications.
The timeline problem
Push delivers updates in real time but struggles at scale; pull handles millions of clients but adds latency (see push vs pull). A Twitter timeline needs both: instant loads for active users and sensible resource use for hundreds of millions of accounts.
Alice follows 500 accounts; some post constantly, others weekly. When she opens Twitter, her timeline must show the recent tweets of all 500, sorted by time. The simple approach is to query on demand: fetch recent tweets from every followed account, merge, sort, return. That's pull. It works for small follow counts but breaks at scale: querying 500 accounts and sorting thousands of tweets takes time, and every timeline load repeats the work.
Fan-out on write (push)
When Bob tweets, the system immediately writes the tweet into the timelines of all his followers. With 1,000 followers, that's 1,000 inserts into precomputed timelines. When Alice opens Twitter, her timeline is already built: read it and display it, with no merging or sorting. One write creates many copies, and the timeline becomes a cache. Reads are fast because the work happened at write time.
- Pros: very fast, predictable reads; the work happens off the request path.
- Write amplification: a celebrity with 50 million followers tweets, and the system must write 50 million timelines. One tweet becomes 50 million operations, creating massive write spikes.
- Storage blow-up: every tweet is stored once per follower timeline; a tweet seen by 10,000 users is stored 10,000 times. Storage grows with follower count × tweet volume, prohibitive for accounts with millions of followers.
- Wasted work for inactive followers, and edits or deletes must touch many timelines.
Fan-out on read (pull)
Don't precompute. When Alice loads her timeline, fetch recent tweets from all 500 accounts she follows, merge, sort by time and return the top 50. The work happens at read time.
- No write amplification: Bob tweets once and one copy is stored, whatever his follower count. Celebrities and normal users cost the same to write, and storage stays efficient.
- Expensive reads: every load queries 500 accounts, scans thousands of rows, merges and sorts, and heavy users refresh often. Multiply that by millions of active users.
- Higher latency: querying hundreds of accounts plus merging can take several hundred milliseconds, and the experience suffers.
The hybrid approach
Twitter uses both, depending on the author. Most accounts have modest followings, so they use fan-out on write: Bob's tweet goes into 1,000 timelines, manageable, and Alice's timeline loads instantly. Celebrities with millions of followers use fan-out on read: their tweets are stored once, and when Alice loads her timeline the system separately fetches recent tweets from the few celebrities she follows and merges them in.
If Alice follows 490 regular accounts and 10 celebrities, her precomputed timeline holds tweets from the 490 (pushed at write time), and at read time the system queries the 10 celebrities and merges. Alice gets fast loads, and celebrity tweets cause no write amplification.
The switch-over threshold is a tuning knob, for example 1 million followers (some designs use far lower thresholds such as 10,000; see Design Twitter). Below it, push; above it, pull. The right value balances write cost against read complexity.
Implementation details
- Track follower counts and switch an account's strategy when it crosses the threshold. The change is gradual: existing timeline entries stay, and new tweets follow the new pattern.
- Two queries per read: one fetches the precomputed timeline, another fetches recent tweets from high-follower accounts; merge in memory and return the top items.
- Cache celebrity tweets for a few seconds so many users loading timelines share one query (and the hot key doesn't overload one shard; see hot partitions).
- Skip inactive users during fan-out. There's no point maintaining timelines for people who haven't logged in for months; build theirs on demand when they return.
- Store IDs, not full tweets, in timelines, and hydrate content from a cache, so edits show up everywhere; cap timeline length (say the latest ~800 items) and serve older content from a slower path.
- Rank at read time: modern feeds aren't purely chronological; candidates from the precomputed timeline are scored by a ranking model. Use cursor pagination so new posts don't shift pages.
| Push (fan-out on write) | Pull (fan-out on read) | Hybrid | |
|---|---|---|---|
| Read latency | Lowest | High | Low |
| Write cost | Followers × posts | 1 per post | Bounded (no celebrity fan-out) |
| Storage | One copy per follower | One copy | Copies only for regular accounts |
| Celebrity posts | Very slow fan-out | Fine | Fine (pulled) |
| Freshness | Seconds behind (async) | Real time | Mostly seconds behind |
| Best when | Reads far exceed writes | Writes would amplify enormously | Follower counts are highly skewed |
Fan-out on write optimizes reads at the expense of writes, right for most users, who read far more than they post. Fan-out on read optimizes writes at the expense of reads, right for celebrities, whose posts would otherwise reach millions of timelines. The hybrid optimizes the common case and handles the edge case differently, and the idea applies to any system with a highly skewed distribution: e-commerce recommendations, social networks, content feeds.
The general fan-out/fan-in pattern
Beyond timelines, fan-out splits one request into many parallel sub-requests, each handled independently by a different server or shard, and fan-in collects their results into one response. When Alice (following 300 people) loads her timeline on a pull path, the system fans out to fetch recent tweets from each followee; running those queries in parallel across 10 database shards cuts latency from seconds to milliseconds. The pattern appears as parallel reads (feeds, search) and parallel writes (notifications to millions of inboxes).
Fan-out reads
Search engines are the classic case. A query for "system design" searches billions of documents in an index split into 100 shards. The query goes to all 100 at once; each returns its top 10 matches; fan-in merges the 1,000 results into the global top 10. Sequentially, at 50 ms per shard, that would take 5,000 ms. In parallel, the total is roughly the slowest shard plus the merge, on the order of 50–100 ms: a 50× speedup that makes search practical. Product search works the same way: "laptop under $1000" is filtered by price and category on every catalog shard, then merged by relevance. See search.
The catch is stragglers: if 99 shards answer in 50 ms and one takes 500 ms, the whole request waits for it. Fixes include timeouts with partial results, backup requests to replicas, and hedged requests (ask several replicas, use the first answer). See latency vs throughput.
Fan-out writes
A user posts a photo and every follower gets a notification. For a celebrity with 10 million followers, writing 10 million notifications one by one is impossible in reasonable time. Fanning the writes out across hundreds of servers, each handling about 50,000, brings it from hours to seconds. Twitter's home timeline is the same idea (fan-out on write into follower inboxes), with the celebrity exception above.
Aggregation strategies (fan-in)
| Strategy | How it combines | Example |
|---|---|---|
| Merge sort | Merge pre-sorted lists, keeping the order | Search results ranked by relevance from each shard |
| Union | Combine everything, removing duplicates | Posts from several friend groups, deduplicated by post ID |
| Intersection | Keep only results present in every set | "red laptop" = results for "red" ∩ results for "laptop" |
| Aggregation (sum, count, average) | Combine numbers | Total orders = sum of each region's count |
Handling failures
When you query 100 shards, one will eventually fail. The choice is to wait indefinitely, time out and fail, or return partial results:
- Partial results keep the service available: if 99 of 100 shards answer, return those with a flag. Search engines do this routinely; a missing shard costs 1% of results, not the whole query.
- Timeouts stop one slow shard from blocking everything: set a deadline such as 100 ms, include whoever answers in time, and accept slightly incomplete results for bounded latency.
- Backup requests: send to the primary; if it hasn't answered in 50 ms, send to a replica and use whichever answers first. Masks slow or failed nodes with little extra load.
- For fan-out writes, use work queues so batches can be retried, and make each write idempotent so retries don't duplicate notifications. See idempotency.
Where it’s used
Historically pushed tweets into Redis-backed home timelines for most users, and merged in tweets from high-follower accounts at read time.
Precompute candidate posts from followed accounts (fan-out on write), then rank them with ML models at read time.
Every query fans out to all index shards and fans in by merging top results, with timeouts and partial results for stragglers.
One event fans out to millions of devices through work queues and parallel workers.
In an interview
- For a feed, present push and pull, their costs, then the hybrid with a follower threshold for celebrities.
- Quantify write amplification (followers × posts per day) and do the fan-out asynchronously through a queue.
- For search or aggregation, describe fan-out/fan-in across shards, the merge strategy, and how you handle stragglers (timeouts, partial results, hedging).
- Mention skipping inactive users, caching celebrity tweets, and idempotent fan-out writes.