Design a News Feed (Facebook / LinkedIn)
Ranked timeline at FB/LI scale: hybrid fan-out, ML reranker, dwell-time signals, story TTLs, and ad insertion.
Intro
A news feed is the canonical 'rank a stream of heterogenous items per user' problem. Facebook serves ~2 B DAU; each open returns a ranked list mixing posts from friends, pages, groups, ads, and notifications. The architecture has to balance a fan-out pipeline that's already strained by celebrity authors with a sub-100 ms reranker that scores hundreds of candidates per request — and never blocks the page on either.
Functional
- POST /posts (text + media + audience).
- GET /feed — ranked, personalised, paginated.
- Like / comment / share trigger feed-relevant signals.
- Stories (24-hour TTL items) inline with posts.
Non-functional
- Feed read p95 < 200 ms (incl. ranking).
- 2 B DAU; ~100 k QPS read at peak, ~10 k QPS write.
- Avg friends/follows: ~300; outliers: 5k+.
Components
API gateway
Auth, rate-limit, audience-scope ACL.
Feed service
Pulls candidates + invokes ranker.
Fan-out workers
Materialise feed_candidates per user (Kafka consumer).
Ranker
ML reranker on ~500 candidates → top 50.
Embedding store
User + post vectors (Redis / FAISS).
Post store
Cassandra, partitioned by post_id.
Social graph
TAO-style cache + sharded MySQL.
Trade-offs
Fan-out on write vs. read vs. hybrid
Pros
- Hybrid handles celebrities without write-storms while keeping common reads O(1).
Cons
- Two code paths; merging push + pull at read time.
Real-time rerank vs. cached ranking
Pros
- Real-time captures dwell-time signals fresh; cached saves CPU.
Cons
- Stale rankings degrade UX; freshness budget tied to model SLA.
Scale concerns
- Celebrity / page outliers — pull at read.
- Story TTL eviction — separate hot store with 24 h expiry.
- Ad slots — must merge ranked organic with ad-served candidates without skewing CTR.