Deep dive · Hard
Design a news feed
The most-asked design question, because it forces the single most important architectural instinct: deciding whether work happens at write time or read time — and knowing that the real answer is usually both.
What it trains: Fan-out on write vs read, ranking, the celebrity problem
1. Requirements
Functional
- Post content (text, image, video)
- View a feed of posts from accounts you follow, newest or ranked first
- Follow and unfollow accounts
- Interact: like, comment, share
Non-functional
- Feed load under ~200ms — this is the app's core interaction
- Read-heavy: roughly 100:1 reads to writes
- Eventual consistency is acceptable; a post appearing a few seconds late is fine
- Highly available: a stale feed beats no feed
2. Back-of-envelope numbers
- 300M daily users × 5 feed loads ≈ 1.5B reads/day ≈ 17K QPS, ~50K at peak
- 2M posts/day ≈ 25 writes/sec — writes are trivial, fan-out is not
- Average 200 followers means one post = 200 timeline writes: 5M timeline writes/sec at peak if done naively
- A cached timeline of 500 post IDs × 8 bytes ≈ 4 KB per user; 300M users ≈ 1.2 TB of Redis — large but affordable
3. Architecture
WRITE PATH READ PATH
┌────────┐ ┌────────┐
│ Author │ │ Reader │
└───┬────┘ └───┬────┘
│ POST /posts │ GET /feed
┌───▼─────────┐ ┌─────▼──────┐
│ Post service│ │Feed service│
└───┬─────────┘ └──┬──────┬──┘
│ │ │
┌───▼──────┐ ┌──────────────┐ ┌────▼───┐ │ pull for
│Post store│ │ Fan-out │ │ Redis │ │ celebrities
│(Cassandra│──▶│ workers │────▶│timeline│ │
│ / S3) │ │ (Kafka) │ │ cache │ │
└──────────┘ └──────┬───────┘ └────────┘ │
│ skip if author is │
│ a "celebrity" │
┌──────▼───────┐ ┌────▼────────┐
│Follower graph│ │ Ranking svc │
└──────────────┘ │ + hydration │
└─────────────┘Hybrid fan-out: normal authors are pushed into follower timelines at write time; celebrities are merged in at read time.
Two candidate architectures
Fan-out on write (push): when someone posts, append the post ID to every follower's precomputed timeline in Redis. Reads become one cache lookup. Fan-out on read (pull): store posts once, and at read time fetch the recent posts of everyone you follow and merge. Writes become trivial, reads become expensive.
Why the answer is hybrid
Push is right for the 99.9% of users with a few hundred followers. It breaks for an account with 50 million followers — one post triggers 50 million writes, and the fan-out lag can reach hours. So: push for normal accounts, pull for celebrities, and merge the two lists at read time. State this explicitly with the number that justifies it.
Data model
posts (post_id, author_id, content_ref, created_at), follows (follower_id, followee_id) sharded by follower for the 'who do I follow' query, and timelines as a Redis sorted set per user, capped at ~500 entries. Store post IDs, not post bodies — hydrate content in a second batched fetch so an edited or deleted post is never stale in a million timelines.
4. Deep dives
This is where levels are decided. Go deep on one or two of these rather than shallow on all of them.
The fan-out pipeline
Posting writes to the post store, then emits an event to Kafka. Fan-out workers read the author's follower list and push the post ID into each follower's Redis timeline. This is asynchronous, so it must be idempotent and retryable — workers will replay. Cap timelines at 500 entries and drop the tail; nobody scrolls that far, and inactive users' timelines can be dropped entirely and rebuilt on next login.
The celebrity problem
Define a threshold — say 100,000 followers — above which an author is not fanned out at all. At read time, the feed service loads the user's precomputed timeline and separately fetches recent posts from the handful of celebrities they follow, merges by score, and returns. Cost is bounded because a user follows few celebrities, and celebrity posts are cached once and read by everyone.
Ranking
A chronological feed is a fallback; real feeds rank. Take a few hundred candidates from the merged timeline, apply a lightweight scoring model over features (recency, affinity with the author, engagement rate, media type), and return the top 20. Keep ranking out of the fan-out path: rank at read time so the model can change without rebuilding a billion timelines.
Hydration and content delivery
Timelines hold IDs. Hydration is a batched multi-get against the post store plus a user cache for author metadata. Images and video live in blob storage behind a CDN, uploaded directly by clients via presigned URLs — never through your application servers.
Consistency and edge cases
Unfollowing does not retroactively clean timelines; filter at read time instead. A deleted post is filtered during hydration. New follows backfill from the followee's recent posts. Each of these is a place candidates hand-wave — naming them shows you've actually operated a system like this.
5. Tradeoffs to argue
Push vs pull fan-out
Upside: Push gives sub-100ms feed loads from one cache read
Cost: Write amplification of 200×–50M×, and hours of lag for huge accounts
Store IDs vs full posts in timelines
Upside: IDs keep memory small and content always fresh
Cost: An extra hydration round trip per feed load
Chronological vs ranked
Upside: Ranking lifts engagement substantially
Cost: Read-time compute, model infrastructure, and much harder debugging
6. Questions the interviewer will ask
- A user with 50 million followers posts. Walk me through exactly what happens.
- How long after posting does a follower see it, and where does that latency come from?
- A user has been inactive for a year and logs in. What does their timeline look like?
- Your Redis timeline cluster loses a node. How do you rebuild it?
7. Mistakes that sink this answer
- Choosing pure push or pure pull without addressing where it breaks
- Storing full post content in every follower's timeline
- Ignoring ranking entirely when the prompt implies a modern feed
- Missing the unfollow, delete, and new-follow backfill cases
Practice this live
Run a mock system design interview and get scored against your target level.
Other problems
URL shortener
Hashing, ID generation, read-heavy caching, simple sharding
Chat / messaging
WebSockets, ordering, delivery guarantees, presence
Ride sharing
Geospatial indexing, matching, real-time state
Rate limiter
Token bucket, sliding window, distributed counters
Web crawler
Queues, deduplication, politeness, horizontal scale