Design Facebook News Feed
DifficultyMedium | HelloInterview: problem breakdown
Problem Statement
Design a news feed system where users can publish posts and see a personalized, ranked feed of posts from people they follow. Think Facebook, Instagram, Twitter timeline.
๐Real-world: The feed is the home of the "fan-out on write vs fan-out on read" tradeoff, and the canonical war story is Twitter's celebrity problem: precomputing each user's timeline on write (push) is great for normal users but explodes for accounts with tens of millions of followers โ when Lady Gaga tweets, you can't synchronously write to 80M inboxes. Twitter's real architecture became a hybrid: push for most users, but pull (compute at read time) for celebrity posts, merged in when you load your feed. The early Twitter that couldn't handle this gave us the legendary "fail whale." Security/integrity angle for this audience: the modern feed is also a ranking and trust-and-safety battleground โ spam, coordinated inauthentic behavior, and misinformation are filtered in the same pipeline that ranks for engagement, so "the feed" is as much an abuse-detection system as a distributed-systems one.
Requirements
Functional
- Users can create posts (text, images, links)
- User sees a ranked feed of posts from people/pages they follow
- Feed is paginated
- Feed is somewhat real-time (new posts appear within minutes)
Non-Functional
- 500M daily active users
- Average user follows 300 others
- Peak: 5M posts/s (like spikes during events)
- Feed read latency: < 200ms P99
- Eventual consistency is acceptable (slight staleness is OK)
Scale Estimation
- Write: 500M users ร 10 posts/day / 86400 = 58k posts/s average
- Read: 500M users ร 10 feed loads/day / 86400 = 58k feed reads/s average
- Fan-out: each post written โ pushed to followers' feeds. Average 300 followers = 17M feed writes/s (!)
- Celebrity problem: Justin Bieber with 100M followers = 100M feed writes per post (!)
Core Design
The fundamental choice: fan-out on write vs fan-out on read.
Fan-Out on Write (Push Model)
User posts โ Post Service โ Fan-out Worker Queue
โ
For each follower: write post_id to their feed cache
โ
Feed Cache (Redis)
โ
User loads feed โ read from cachefeed reads are fast (pre-computed, just read from cache)
celebrity posts trigger massive write fan-out (100M writes for 1 post)
storage cost (storing N copies of every post)
Fan-Out on Read (Pull Model)
User loads feed โ Feed Service โ fetch following list
โ
Query N "post" tables for each followee
โ
Merge + rank โ returnwrites are cheap (post once, no fan-out)
reads are expensive (N DB queries per feed load โ can't scale)
Hybrid Model (Production Reality)
Regular users (< 1000 followers): fan-out on write โ pre-populated feed cache
Celebrity users (> 1M followers): fan-out on read โ fetched and merged at read timeAt feed load time:
- Read pre-computed feed IDs from Redis (regular followees)
- Fetch last N posts from celebrity followees directly
- Merge + rank all posts
- Return paginated result
Architecture
Post Service (write)
|
โโโโโโโโโโโโดโโโโโโโโโโโโโโโ
โ โ
Fan-out Queue Post DB (Cassandra/DynamoDB)
โ โ
Fan-out Workers Object Store (S3 for media)
โ
Feed Cache (Redis)
{user_id: [post_id, post_id, ...]}
Feed Service (read)
|
Check Redis Cache
+ Merge celebrity posts
+ Hydrate post data (Post Service)
+ Ranking (ML model)
โ ResponseData Models
Posts DB (Cassandra โ wide-column, excellent for time-series queries):
posts_by_author(
author_id UUID,
created_at TIMESTAMP,
post_id UUID,
content TEXT,
media_urls LIST<TEXT>,
like_count INT,
...
PRIMARY KEY (author_id, created_at DESC)
)Feed Cache (Redis):
Key: feed:{user_id}
Value: sorted set of post_ids ordered by rank_score
TTL: 24 hours (rebuild on miss)Ranking
Simple scoring: score = base_time_decay + engagement_boost + affinity_score
- Can be a lightweight ML model or simple formula
- Applied during fan-out write OR at read time (trade latency for freshness)
Key Design Decisions
| Decision | Choice | Reason |
|---|---|---|
| Fan-out | Hybrid (write for normal, read for celebs) | Balances write load vs read latency |
| Post storage | Cassandra | Time-series read pattern per author; high write throughput |
| Feed storage | Redis sorted set | O(log N) insert, O(1) range read, TTL-based GC |
| Media | S3 + CDN | Blob storage + edge caching |
| Consistency | Eventual | Social feed staleness is acceptable |
Security Considerations
| Threat | Mitigation |
|---|---|
| Privacy / visibility control | Feed worker checks privacy settings before fan-out (public vs friends-only posts) |
| Feed poisoning | Validate post content at write time; scan for malware URLs |
| Mass DM / spam account | Rate limit post creation; ML spam classifier |
| Account takeover โ defacement | 2FA on accounts; post velocity alerts for suspicious activity |
| Data exfiltration via feed API | Paginate responses; no bulk export API; authentication required |
| SSRF via link preview | Preview link metadata in sandboxed environment; block internal IPs |
| Stored XSS via post content | Sanitize HTML/markdown at write time; Content-Security-Policy on frontend |
Interview Tips
spend time on push vs pull vs hybrid.
(Justin Bieber problem) is the famous gotcha โ you must handle it.
even a simple formula shows you understand feed relevance is not just chronological.
is the canonical answer for feed cache storage.
say it explicitly and explain why (user won't notice 30-second staleness in a social feed).