Part VI β The Blueprint Β· Lesson 11.4
HLD β News Media Feed (Facebook, Twitter)
In one lineA cursor-paginated list that must accept live inserts without ever moving content under the reader.
Where you've seen itThe "12 new posts" pill at the top of a timeline β the polite alternative to yanking the page.
Diagram
1β2 Β· SCOPE AND SCALE
in scope timeline Β· post detail Β· compose Β· like/repost/reply
out DMs Β· search Β· trends Β· ads Β· moderation
scale 300M DAU Β· ~50 posts/session Β· live updates every few sec
mixed media, mostly text + one image3β4 Β· ARCHITECTURE AND DATA
ββββββββββ GET /feed?after=<cursor> βββββββββββ
β Client ββββββββββββββββββββββββββββββΊβ BFF ββββΊ feed service
βββββ¬βββββ βββββββββββ (ranking)
β SSE / WebSocket (2.5 / 2.4)
βΌ
live events: post.created Β· post.liked Β· post.deleted
normalized store (6.6)
posts: { p7: {...} } users: { u1: {...} }
feed: ['p9','p8','p7'] β order separate from entities6a Β· DEEP DIVE β LIVE INSERTS WITHOUT DISRUPTION
user at top user scrolled down
ββββββββββββββββββββ ββββββββββββββββββββ
β [ 12 new posts β²]β β post 40 β
β post 9 β β post 41 β
β post 8 β β post 42 β
ββββββββββββββββββββ ββββββββββββββββββββ
click β prepend + buffer silently; scroll anchor
scroll to top stays fixed (10.13)
Insert immediately ONLY if scrollTop === 0 and the tab is focused.6b Β· DEEP DIVE β WHY OFFSET PAGINATION BREAKS HERE
offset page 2 returns posts already seen, because 12 new
posts shifted every index (10.11)
cursor after=<p7> β always the item AFTER p7,
regardless of what arrived above it
Cursor = base64(rankScore | postId) so it survives
ranked (non-chronological) feeds too.How it works
- Cursor pagination everywhere; offsets are unusable on a feed that receives inserts.
- Normalized store so one
post.likedevent updates the post in the timeline, the detail view, and the profile at once. - Buffer live inserts behind a pill; auto-insert only when the user is genuinely at the top.
- Virtualize past a few hundred items (10.7), and preserve scroll position on back-navigation.
- Optimistic like and repost with rollback; the counter is derived, never separately stored.
Trade-offs
| Choice | Cost |
|---|---|
| Buffered inserts | Feed is briefly stale by design |
| Ranked (non-chrono) feed | Cursor must encode the rank score |
| Virtualization | Loses native in-page find, complicates SEO |
| SSE for updates | One-way only β compose still uses REST (2.5) |
Interview angle
"New posts arrive while the user is reading. What do you do?"
- Buffer them and show a count pill; only insert automatically when scroll is at the very top.
- Use cursor pagination so those inserts don't cause duplicates on the next page fetch.
- Patch by id into a normalized store, so a like on one post doesn't re-render the entire list (10.5).
Recap
- Cursor pagination is mandatory the moment items can be inserted.
- Never move content under someone who's reading β buffer and offer.
- Normalize, so one event updates every view of that entity.