Design a news feed
Open a social app and your home feed shows recent posts from the people you follow, in under a second, however many people that is. Behind it is one of the classic trade-offs in system design: do the work when someone posts (copy the post into every follower's feed) or when someone reads (gather posts from everyone they follow)? The answer is "both", and the reason is celebrities. It follows the interview framework phase by phase.
1. The prompt
"Design the home timeline for a social network like Twitter/X or Instagram. Users post, follow other users, and see a feed of posts from the accounts they follow."
Posting and following are simple. The interview is about the read path: making a feed of posts from hundreds of accounts appear in a few hundred milliseconds for 60,000 feed loads a second, when some of those accounts have 100 million followers.
2. Frame the problem
How many users, and how many accounts does a typical user follow?
200M daily users; a few hundred followed accounts on average; some accounts have 100M+ followers.
The spread between normal and celebrity accounts decides the fan-out strategy.
Chronological or ranked?
Ranked, but with a chronological option.
The design produces a candidate set; a ranking service orders it. Ranking internals are out of scope.
How fresh must the feed be?
Followers should see a new post within a few seconds; the author immediately.
Eventual consistency for followers, read-your-writes for the author.
Does the feed include media?
Images and videos, stored separately.
Media goes to blob storage and a CDN (Module 10); the feed carries keys.
Infinite scroll, and how far back?
Infinite scroll; a few days of posts in the feed, older ones via profiles.
Timelines can be capped (say 800 entries), with cursors for paging.
What happens when a post is deleted, or an account goes private?
It must disappear from feeds within seconds.
We need a way to hide a post everywhere at once, without rewriting millions of timelines.
Any read/write ratio hints?
People read feeds far more than they post, roughly 20:1.
Precompute at write time to make reads cheap.
3. What it must do
- A user can create a post (text and media).
- A user can follow and unfollow other users.
- A user can view their home feed of posts from followed accounts, ranked, with infinite scroll.
Not now:
- The ranking model itself: we design the pipeline around it.
- Comments, likes UI and search: separate services.
- Ads: inserted by a separate service into the ranked list.
4. How well it must do it
| Target | Why this number |
|---|---|
| Fast feeds: first page under 300 ms at p99 speed | The feed is the first screen of the app. |
| Scale: 200M daily users, 60,000 feed loads a second at peak, accounts with 100M+ followers load shape | Celebrity accounts make fan-out wildly uneven. |
| Fresh enough: followers see a post within ~5 s; the author at once consistency or availability | Availability matters more than strict ordering; nobody notices a few seconds. |
| Deletes are fast: a deleted or hidden post vanishes from every feed within ~5 s security · rules | Privacy and legal takedowns can't wait for caches to expire. |
| Posts never lost data safety | Feeds can be rebuilt; posts can't. |
5. Numbers that change the design
| Quantity | Working | → so we… |
|---|---|---|
| Posts | 200M users × 0.5 posts a day ÷ 10⁵ s | ~1,000/s; ~3,000/s at peak |
| Feed reads | 200M × 10 feed loads a day ÷ 10⁵ | ~20,000/s; ~60,000/s at peak → so reads must be cheap: precompute |
| Fan-out on write | 1,000 posts/s × 200 followers on average | ~200,000 timeline inserts/s → so an in-memory timeline store |
| One celebrity post | 100M followers | 100M inserts for one post → so we don't push celebrity posts |
| Timeline cache | 100M active users × 800 post IDs × 8 bytes | ~640 GB → so a sharded Redis cluster, keyed by user |
6. The nouns
- User.
- Post.
- Follow: a follower and the account they follow.
- Timeline: per user, a capped list of post ids, newest first.
posts post_id (time-ordered, Snowflake-style), author_id, text, media_keys, created_at, status (live | deleted) follows (follower_id, followee_id), plus a reverse index followee_id → followers (sharded by user) timelines user_id → [post_id, …] (latest 800, in Redis sorted sets or lists) users user_id, follower_count, is_celebrity (follower_count over the threshold)
7. The contract
REST, with the user from the session token.
POST /v1/posts {text, media_keys} → 201 {post_id}
POST /v1/follows {followee_id} → 204
DELETE /v1/follows/{followee_id} → 204
GET /v1/feed?cursor=<post_id>&limit=20 → {posts: [...], next_cursor}
GET /v1/feed/new?since=<post_id> → count of newer posts ("12 new posts")
Post ids are time-sortable (Module 20), so "newest first" is "largest id first", and the cursor is just the last id seen.
8. First working version
A post service with a posts table, a follow service with a follows table, and a feed service that assembles feeds on demand.
8.1 Posting
The post service stores the post once with a time-sortable id and confirms. Media was uploaded straight to blob storage beforehand.
8.2 Following
Insert a row in the follows table, and in the reverse index (who follows this account).
8.3 Reading the feed (pull)
Version one pulls: look up the accounts the user follows, fetch each one's recent posts, merge by id, and take the top 20.
Parked for later (section 9 fixes each)
- Pulling 400 accounts' posts on every one of 60,000 feed loads a second is far too slow.
- Pushing instead would cost 100M writes for one celebrity post.
- Where do timelines live, and what about users who never open the app?
- Turning 20 post ids into 20 full posts with authors and counts, quickly.
- New posts arriving while someone scrolls.
- Deleted posts living on in millions of precomputed timelines.
9. Make it hold up
9.1 Fan-out on write, on read, or both? fast feeds · scale
| Approach | Why | |
|---|---|---|
| ✗ Bad | Pull only: on every feed load, query the latest posts of everyone the user follows and merge | Following 500 accounts means 500 lookups (or a huge scatter-gather) per feed load, 60,000 times a second. Too slow and too expensive. |
| ~ Good | Push only: when someone posts, append the post id to every follower's timeline | Reads become one list fetch. But one celebrity post means 100M writes, delaying everyone's feeds behind it, and most of those followers aren't even online. |
| ✓ Great | Hybrid: push posts from normal accounts; for accounts above a follower threshold (say 100K), don't fan out; at read time, merge the user's precomputed timeline with recent posts from the few celebrities they follow | Fan-out work stays bounded; reads add only a handful of lookups (users follow few celebrities), each served from a hot cache. Try the numbers in section 13. |
9.2 Storing timelines fast feeds · scale
- A timeline is a capped list of post ids (the latest 800) per user, in Redis or Valkey, sharded by user id. Ids, not full posts: a post appears in thousands of timelines but is stored once.
- Skip inactive users: don't fan out to followers who haven't opened the app in 30 days. If one returns, rebuild their timeline on demand by pulling once.
- The timeline cache is rebuildable from the follow graph and posts, so losing a shard means slower feeds for a while, not lost data.
- Fan-out workers read followers in pages from the reverse index and write in batches; they're fed by a "new post" event stream, so posting never waits for fan-out.
9.3 Hydrating posts quickly fast feeds
A feed page needs 20 full posts: text, author name and avatar, like counts. Fetch the 20 post objects from a post cache in one batch (MGET), the authors from a user cache, and counters from a counter store; fill misses from the databases. Like counts can be slightly stale (Module 16). The posts table itself is sharded by post id (or author id) in a wide-column or relational store.
9.4 Pagination and freshness fresh enough
Cursor pagination by post id (Module 07) keeps infinite scroll stable while new posts arrive. Posts that arrive after the user opened the app are counted with "newer than the first id I have" and shown behind a "new posts" button, rather than shifting the page under the reader's thumb. The author's own new post is inserted into their own timeline synchronously, so they see it at once.
9.5 Ranking fast feeds
Most feeds are ranked, not purely chronological. Keep the same skeleton:
- The timeline gives a candidate set: a few hundred recent posts from followed accounts, plus recommended ones.
- A ranking service scores them with a model (engagement predictions, freshness), within a strict time budget.
- The top results are returned.
If ranking is slow or down, fall back to chronological order (graceful degradation, Module 24).
9.6 Deletes and privacy changes deletes are fast
A deleted post must vanish quickly from millions of timelines. Rather than removing it from every list, mark the post deleted and evict it from the post cache: hydration skips it, so it disappears everywhere at once, and timelines are cleaned lazily. The same filter handles blocked users and accounts that went private.
9.7 The whole design after the deep dives
A normal user posts, a celebrity posts, and a follower opens their feed: the hybrid in motion.
10. Interviewer follow-ups
A user follows a new account. When do its posts appear?
Backfill asynchronously: a job copies the account's recent post ids into the follower's timeline (or, for a celebrity, nothing needs copying: they're merged at read time). Unfollow removes them lazily via a filter at hydration.
Where exactly is the celebrity threshold?
Tune it with numbers: fan-out cost (posts × followers) against read cost (celebrities followed per user). Many systems also treat very active posters specially. It's a parameter, not a law.
Traffic grows 10×.
More timeline shards, a stricter inactivity cut-off, more fan-out workers, and a lower celebrity threshold to cap write amplification. Hydration caches scale horizontally.
A celebrity's post goes viral; a million people open it at once.
That post is a hot key in the post cache. Keep it in process memory on feed servers for a few seconds and replicate it across cache shards. Like counters use sharded counters merged periodically (Design D20).
Multi-region?
Posts replicate to every region; fan-out runs per region into regional timeline caches; each user's feed is served from their home region. A few seconds of cross-region lag is within the targets.
The timeline cache shard is lost.
Those users' feeds fall back to pull-and-merge (slower but correct) while timelines are rebuilt from the follow graph and posts in the background. Throttle rebuilds so they don't overload the posts database.
How do you measure that the feed is "good"?
Latency and errors for health; engagement (time spent, interactions) and freshness (age of the newest post shown) for quality; A/B tests for ranking changes.
Edit a post after it's been fanned out?
Timelines hold ids, so edits only change the post object; evict it from the post cache and every feed shows the new version at the next read.
Add trending topics.
Count hashtags and phrases from new posts in a stream processor over sliding windows (say 5 and 60 minutes), compare each with its usual rate so steady giants don't always win, and keep the top few hundred per region in a sorted set refreshed every minute (the heavy-hitters approach of Design D20). Filter spam and coordinated bursts before ranking.
Add search over posts.
Stream new posts into a search index (an inverted index sharded by document, Design D26), with a small real-time index so posts are searchable within seconds and a ranking that weighs recency and engagement. The feed's stores stay the source of truth.
11. When things break
| Failure | What users see | How we detect it | What limits the damage |
|---|---|---|---|
| Fan-out workers fall behind | New posts appear late | Event consumer lag | Autoscale workers; pull recent posts for lagging users |
| Timeline shard lost | Slower feeds for some users | Cache errors, miss rate | Pull-and-merge fallback; background rebuild |
| Ranking service slow | Chronological feed | Ranking latency over budget | Timeout and fall back to chronological order |
| Post cache cold | Slow hydration | Hit rate drop | Batched reads from replicas; warm the hottest posts first |
| Celebrity posts at the same time as a spike | Nothing | — | Celebrities aren't fanned out; merged at read time from cache |
12. Wrap-up and the clock
Trade-offs we made:
- Hybrid fan-out (bounded writes, a few extra reads).
- Ids in timelines with hydration (store once, extra lookups per read).
- Eventual freshness for followers; read-your-writes for authors.
- Lazy deletion through a filter.
- Ranking with a chronological fallback.
What we'd watch:
- Feed p99.
- Fan-out lag.
- Timeline cache hit rate and memory.
- Ranking latency and fallback rate.
- Time from post to followers' feeds.
At 10×:
- More shards and workers.
- A lower celebrity threshold.
- A stricter inactivity rule.
A 45-minute interview
| 0–4 | Frame the problem (follower spread, ranked, freshness) |
| 4–9 | Must do, how well, numbers (fan-out maths) |
| 9–13 | Nouns and contract |
| 13–21 | First working version (pull), parked list |
| 21–40 | Deep dives: hybrid fan-out (9.1), timelines (9.2), hydration (9.3), deletes (9.6) |
| 40–45 | Follow-ups and wrap-up |
A 60-minute interview
| 0–5 | Frame the problem |
| 5–11 | Must do, how well, numbers |
| 11–16 | Nouns and contract |
| 16–25 | First working version |
| 25–50 | Deep dives 9.1–9.6 and the final picture |
| 50–60 | Follow-ups: new follows, thresholds, regions; wrap-up |
| Level | What a strong answer shows |
|---|---|
| Mid-level | Posts, follows and feed APIs; push vs pull explained; a timeline cache; cursor pagination. |
| Senior | Quantified fan-out, the celebrity problem and the hybrid, hydration with batched caches, inactive users, delete handling. |
| Staff+ | Ranking pipeline and fallbacks, threshold tuning, rebuilding timelines, multi-region, cache cost against compute, and how the design evolves with the product. |
Common mistakes:
- Pull-only feeds at this scale.
- Pushing celebrity posts.
- Storing full posts in every timeline.
- Fanning out to inactive users.
- Offset pagination.
- Deleting from millions of lists synchronously.
13. Try it, check yourself, read more
Compare the work each strategy does. "Celebrities" are accounts above the threshold; each user follows a few of them.
Hybrid assumes each user follows about 5 celebrities, whose recent posts are read from a hot cache at feed time.
Why not fan out a celebrity's posts on write?
What do precomputed timelines store?
How do you make a deleted post vanish from millions of feeds at once?
How does an author see their own post immediately?
| Resource | Why |
|---|---|
| Designing Data-Intensive Applications, chapter 1 | Uses Twitter's home timeline as its running example of load and fan-out. |
| Design a news feed (Hello Interview) | Another walkthrough with the hybrid fan-out. |