Chapter 19 — Design a News Feed (Instagram / Twitter)
Chapter 19 — Design a News Feed (Instagram / Twitter)
Hey everyone! Welcome back to Namaste System Design! 🙏
The news feed is a favorite interview question because it hides a genuinely hard problem: the fan-out. When you open Instagram, how does it instantly assemble posts from the hundreds of people you follow, out of billions of posts? And how does the system survive when a celebrity with 500 million followers posts? Let's solve it with the framework.
Step 1 — Clarify Requirements
FUNCTIONAL:
✔ User can post (text/image)
✔ User can follow others
✔ User sees a FEED of recent posts from people they follow
✔ Feed roughly reverse-chronological (or ranked)
NON-FUNCTIONAL:
✔ VERY read-heavy (people scroll way more than they post)
✔ Feed must load FAST (< 200ms) — the core UX
✔ Highly available; eventual consistency is OK
(a post appearing 2s late is fine — recall Ch 09/14)
SCOPE: "Focus on generating and serving the feed. I'll assume
eventual consistency and reverse-chronological order."
Step 2 — Estimate Scale
300M daily active users
Each opens the feed ~10×/day → 3B feed reads/day ≈ 35,000 reads/sec
Posts: say 1 per user per 2 days → ~1,700 writes/sec
→ Reads ≫ writes. The feed READ must be pre-computed & cached,
NOT calculated live from billions of posts on each open.
Step 3 — The Core Question: Fan-out
How do we build each user's feed? Two fundamental approaches — this is the entire interview.
┌─────────────────────────────────────────────────────────────┐ │ FAN-OUT ON READ (pull model) │ │ Build the feed WHEN the user opens the app: │ │ "Get latest posts from all 500 people I follow, merge, │ │ sort by time." → done live, per request. │ │ │ │ + writes are cheap (just save the post once) │ │ − reads are SLOW & expensive (query many users every open)│ │ │ │ │ │ FAN-OUT ON WRITE (push model) │ │ Build feeds WHEN someone posts: │ │ "I post → immediately PUSH it into the pre-built feed │ │ cache of every one of my followers." │ │ │ │ + reads are INSTANT (feed is already built ⚡) │ │ − writes are expensive (1 post → millions of inserts) │ └─────────────────────────────────────────────────────────────┘
FAN-OUT ON WRITE (the usual default):
Aisha posts ──▶ [ fan-out service ]
│ push post-id into each follower's
▼ feed list (in Redis)
follower1 feed: [new, ...] follower2 feed: [new, ...] ...
Later, follower opens app → their feed is ALREADY built →
just read a pre-made list from Redis. Instant. ✅
Step 4 — High-Level Design
POST FLOW (write):
[Client] → [LB] → [Post service] → save post in DB
│
▼ (async via a QUEUE — Ch 10)
[ Fan-out service ]
│ for each follower, push post-id
▼ into their feed cache
[ Redis feed cache ] feed:userX → [id, id...]
READ FLOW (feed):
[Client] → [LB] → [Feed service]
│ read pre-built list feed:userX
▼ from Redis (post-ids)
hydrate post-ids → full posts (from cache/DB)
▼
return feed ⚡
Notice fan-out runs asynchronously via a message queue — the poster doesn't wait for millions of inserts.
Step 5 — Deep Dive: The Celebrity Problem
Fan-out-on-write breaks for celebrities. If Ronaldo (500M followers) posts, we'd do 500 million inserts for one post — a "fan-out storm" that could take minutes and hammer the system.
Regular user posts → push to ~500 feeds. Fine. ✅ Celebrity posts → push to 500,000,000 feeds. 💥 disaster.
The elegant solution — a HYBRID approach:
┌─────────────────────────────────────────────────────────────┐ │ HYBRID (push for normal, pull for celebrities): │ │ │ │ • Normal users → FAN-OUT ON WRITE (push to followers) │ │ │ │ • Celebrities → do NOT fan out. Their posts are PULLED │ │ at read time. │ │ │ │ When you open your feed: │ │ 1. read your pre-built feed (normal people's posts) │ │ 2. + fetch recent posts from the few celebrities you │ │ follow (live) and MERGE them in │ │ │ │ Best of both: fast reads AND no fan-out storms. 🌟 │ └─────────────────────────────────────────────────────────────┘
This hybrid is exactly what real systems like Twitter use. Explaining it clearly is a strong signal.
Step 6 — Bottlenecks & Trade-offs
⚠ Feed cache memory → store post-IDs only (not full posts);
cap feed length (e.g. latest 500)
⚠ Fan-out lag → eventual consistency; a post may take
seconds to reach all feeds (acceptable)
⚠ Hydration cost → cache the post objects too, so turning
IDs into full posts is fast
⚠ Ranking → reverse-chron is simple; real feeds add
an ML ranking layer (out of scope)
⚠ Inactive users → don't pre-build feeds for users who
never log in (waste) → pull for them
Interview Questions — Quick Fire!
Q: What's the difference between fan-out on read and fan-out on write?
"Fan-out on read, or pull, builds the feed when the user opens the app by querying all the people they follow and merging the results — cheap writes but slow, expensive reads. Fan-out on write, or push, builds feeds at post time by pushing the new post into every follower's pre-built feed cache — instant reads but expensive writes. Since feeds are extremely read-heavy, push is usually preferred so reads are fast."
Q: How do you handle the celebrity problem?
"Fan-out on write breaks for celebrities because one post would require hundreds of millions of feed inserts. The solution is a hybrid: use push for normal users, but for celebrities don't fan out at all — their posts are pulled live at read time. When a user opens their feed, we read their pre-built feed and merge in recent posts from the few celebrities they follow. This gives fast reads without fan-out storms."
Q: Why is fan-out done asynchronously?
"Because pushing a post to potentially thousands of followers' feeds shouldn't block the person posting. The post is saved quickly and a fan-out job is placed on a message queue; a background service then updates all the follower feeds. The user gets an instant confirmation while the heavy work happens asynchronously, and eventual consistency — a post appearing in feeds a second or two later — is perfectly acceptable here."
Q: What do you store in the feed cache — full posts or IDs?
"Just post IDs, to save memory, since the same post appears in many feeds. At read time we hydrate the IDs into full post objects, ideally from a separate post cache so hydration is fast. We also cap each feed's length, keeping only the most recent few hundred entries."
Key Points to Remember
| Concept | Key Takeaway |
|---|---|
| Core problem | Fan-out: how to assemble a feed fast. Read-heavy → pre-compute feeds. |
| Push (write) | Build feeds at post time → instant reads, expensive writes. Usual default. |
| Pull (read) | Build feeds at read time → cheap writes, slow reads. |
| Celebrity problem | Hybrid: push for normal users, pull for celebrities, merge at read time. |
| Async fan-out | Do fan-out via a queue; store post-IDs; eventual consistency is fine. |
What's Next?
Chapter 20 tackles real-time communication: Design a Chat App (WhatsApp). We'll meet WebSockets, online presence, and how to deliver a message the instant it's sent — even when the recipient is offline.
Keep designing, keep scaling! See you in the next one!
Post a Comment