Vibe Engines
YouTube
System Design

Design a News Feed

Step 1 / 9

Learn system design by building a social news feed step by step.

The numbers to beat2,000follows to mergeeveryrefresh re-queriesfreshbut slow

The whole design, in writing

Learn system design by building a social news feed step by step. An interactive guide covering the social graph, pull vs push fan-out, a precomputed feed cache, ranking, the hybrid model for celebrities, mixing content sources, and pagination.

Every step of the build above, written out: the problem each piece solves, the option that was taken and the ones that were not, the numbers, and how it fails in production.

The big idea

What is a news feed?

Open the app and you see a personalized stream of posts from everyone you follow, freshest and most relevant on top. Simple to use — but building one reader’s feed means merging posts from hundreds or thousands of authors, ranking them, in a few hundred milliseconds, for billions of readers.

Authorcreates a postReaderopens the app
New in this step: Author, Reader.

The whole game is when you do the work: merge everyone’s posts at read time (simple, slow) or pre-build each feed at write time (fast reads, heavy writes). We’ll start naive and evolve into the hybrid that real feeds use.

What the new pieces do

Authorclient
Anyone who publishes. A normal user has hundreds of followers; a celebrity has millions — and that difference reshapes the whole design.
Readerclient
Pulls down to refresh and expects a fresh, ranked feed in a few hundred milliseconds. Reads vastly outnumber posts.

Step 1 · The skeleton

Post and read

Two operations: an author publishes a post, and a reader asks for their feed. Both go through one place, and the post content has to live somewhere durable. How should feeds refer to posts?

Feed APIPost Store
New in this step: Feed API, Post Store. · swipe to pan the diagram

A post can appear in millions of feeds. How should those feeds store it?

  1. Now an edit or delete must hunt down millions of copies, and storage explodes. Duplicated content turns every change into a distributed cleanup problem.

  2. One durable copy in the Post Store; feeds hold only IDs and hydrate bodies at read time. Edits, deletes and privacy changes resolve correctly everywhere, for free.

  3. That’s pure pull — every reader re-queries every author they follow on each refresh. Simple, but it makes the hot read path do all the work (the next step’s problem).

Stand up a Feed API with a Post Store behind it. Writing a post saves a row; reading a feed will (for now) go figure out what to show. This is the spine everything else hangs off.

What the new pieces do

Feed APIbackend
The entry point for both posting and reading. It assembles a reader’s feed and accepts an author’s new posts.
Post Storestore
The durable home of post bodies, media references and metadata. Feeds store only IDs; this is where the actual content is hydrated from.

Step 2 · The naive read

Pull (fan-out on read)

To build a feed on demand, you’d look up everyone the reader follows in the Social Graph, fetch each one’s recent posts, merge and sort them — every single time they refresh.

Feed APISocial GraphPost Store
New in this step: Social Graph. · swipe to pan the diagram

This pull model is dead simple and always fresh, and writes are trivial (just save the post). But a reader following 2,000 accounts triggers a 2,000-way query and merge on every open — far too slow at scale.

  • 2,000follows to merge
  • everyrefresh re-queries
  • freshbut slow

What the new pieces do

Social Graphservice
Stores the follow edges. To build a feed you first need to know whose posts a reader should even see.

Back of the envelope

follows 2,000 × recent posts
a 2,000-way fetch + merge on every single refresh
reads ≫ writes (~100:1)
paying the big cost on the common operation is backwards
writes are O(1)
posting is just one insert — pull’s one redeeming virtue

Step 3 · Flip the work

Push (fan-out on write)

Reads are the hot path, yet pull does the most work there. We want reading a feed to be a single cheap lookup — which means the answer must already exist before the reader asks. When do you build the feed?

Feed CacheprecomputedFan-out Workerson write
New in this step: Feed Cache, Fan-out Workers.

Reads dominate but pull does its heaviest work on reads. How do you make a feed read O(1)?

  1. It helps a little, but the first reader still pays the full 2,000-way merge, and the cache is cold or stale exactly when new posts arrive. You’re patching pull, not fixing it.

  2. Replicas scale raw query throughput but every read still does the expensive multi-author merge. You’ve made a slow operation parallel, not cheap.

  3. When an author posts, push the ID into every follower’s feed cache. Reading is then O(1) — grab your precomputed list. Work moves from many reads to one write.

When an author posts, Fan-out Workers push the post ID into the Feed Cache of every follower. Reading is now O(1): grab your precomputed list of IDs and hydrate the bodies. Work moved from many reads to one write.

  • O(1)feed read
  • precomputedper follower
  • ×followerswrite cost

What the new pieces do

Feed Cachecache
A ready-made list of post IDs per user. Reading the feed becomes a single fast lookup instead of a live query across everyone they follow.
Fan-out Workersworker
When someone posts, these workers push the post ID into each follower’s feed cache — doing the join once at write time, not on every read.

Back of the envelope

1 post × F followers
F cache inserts at write time — the amplification
typical F ≈ hundreds
cheap: a few hundred tiny ID inserts per post
celebrity F ≈ 50M
50M inserts for one post — push collapses here (step 5)

Step 4 · Newest isn’t best

Ranking

A purely chronological feed buries the post you’d most want to see under noise. Engagement craters when relevance is left to luck and timestamps. How do you order the feed?

Feed CacheprecomputedRankingscore & order
New in this step: Ranking.

A chronological feed buries the best post. How do you order what the reader sees?

  1. Simple and predictable, but a single chatty account drowns the post you actually care about. Recency alone is a weak proxy for relevance.

  2. That hands ranking to the people with the most incentive to game it — every post becomes "top priority". Ordering must be decided by the platform, from signals, not by the author.

  3. Two stages: cheaply gather candidates, then a model orders just those by how close you are to the author, freshness and likely engagement. The same retrieve-then-rank pattern powers search.

Run candidates through a Ranking stage that scores each by affinity (how close you are to the author), recency, and predicted engagement. The feed cache holds candidates; ranking decides their order at (or near) read time.

What the new pieces do

Rankingservice
Scores candidate posts by relevance — affinity, recency, engagement — so the feed shows what matters, not just the newest thing.

Step 5 · The celebrity problem

Go hybrid

Push breaks for the mega-popular: one post by a celebrity with 50M followers means 50M cache writes — a thundering, slow, expensive fan-out that also wastes effort on inactive followers. What do you do for them?

AuthorReaderFeed APISocial GraphFeed CacheFan-out WorkersPost StoreRankingPost Events
New in this step: Post Events. · swipe to pan the diagram

A celebrity with 50M followers posts. Push to all 50M feeds, or something else?

  1. 50M cache writes per post, per celebrity, including for followers who’ll never open the app. You can parallelize it, but it’s enormous wasted work on the write path.

  2. Now every ordinary reader pays the slow multi-author merge again — you’ve thrown away the O(1) reads that push bought you, to fix a problem only celebrities have.

  3. Skip fan-out for the few mega-accounts and merge their recent posts into the precomputed feed on read. The merge set is tiny (a handful of celebs) so reads stay fast and writes stay sane.

Go hybrid. Push for ordinary authors; for celebrities, skip fan-out and let readers pull their recent posts at read time, merging them into the precomputed feed. Route new posts through an event stream so fan-out can absorb spikes and run async.

  • pushnormal authors
  • pullcelebrities
  • mergeat read time

What the new pieces do

Post Eventsbus
A stream of new posts. Fan-out, search indexing and analytics all consume it independently — and it absorbs celebrity-sized spikes.

Back of the envelope

a 10k-follower author ⇒ 10k inbox writes per post
expensive, but bounded — push is still the right call
a 50M-follower account ⇒ 50M writes for that same single post
5,000× the cost of the author above — this one number is why the cutoff exists
so push below ~10k followers, pull above it
the threshold is not a convention; it is where write cost stops being survivable
pull the few thousand mega-accounts
their posts are fetched and merged on read
read = precomputed feed + N celeb pulls
N is single digits, so reads stay fast

Step 6 · More than friends

Mixing sources

A modern feed isn’t only people you follow — it’s followed pages, recommended posts you don’t follow yet, and ads. These come from different systems but must feel like one coherent stream. How do you combine them?

Feed APIFeed CacheFan-out WorkersRankingOther Sources
New in this step: Other Sources. · swipe to pan the diagram

Friends, pages, recommendations and ads all need to share one feed. How?

  1. That’s not a feed, it’s a dashboard — and it ignores relevance across sources. A great recommended post should be able to outrank a dull friend post, which fixed sections forbid.

  2. Friends, pages, recs and ads each emit candidates; a shared ranker scores and interleaves them under one policy (with ad-spacing and diversity rules). Adding a new source is a new generator, not a new feed.

  3. Phones can’t see global ranking signals, the merge logic forks across platforms, and you ship ranking secrets to the client. Blending belongs on the server, in one place.

Gather candidates from each source — friends (feed cache), pages, recommendations, ads — then rank and interleave them under one policy, with rules for ad spacing and diversity so the feed doesn’t clump.

What the new pieces do

Other Sourcesstore
Followed pages, recommended posts and ads. The final feed blends these with friends’ posts under one ranking.

Step 7 · The sharp edges

Pagination, dedup & freshness

Readers scroll for ages, so feeds must page without showing the same post twice or skipping new ones that arrive mid-scroll. And a post deleted after fan-out shouldn’t haunt a million feeds. How do you page an ever-changing feed?

AuthorReaderFeed APISocial GraphFeed CacheFan-out WorkersPost StoreRankingOther SourcesPost Events
The system as it stands at this step. · swipe to pan the diagram

Infinite scroll, with posts constantly inserted and deleted. How do you paginate?

  1. When new posts arrive at the top, every offset shifts — page 2 now repeats items from page 1, or skips some. Offset pagination and a live feed don’t mix.

  2. A stable cursor marks your position so inserts can’t cause dupes or gaps; dedup drops already-seen IDs; and because feeds store IDs, hydration re-checks the Post Store so deleted/edited posts resolve correctly at read time.

  3. Refetching everything is wasteful, janky, and still doesn’t give a stable scroll position — the reader keeps losing their place as the top churns.

Use cursor-based pagination (a stable position, not page numbers) so inserts don’t cause dupes or gaps. De-dupe already-seen IDs per session. Because feeds store IDs, hydration re-checks the Post Store — so deleted or edited posts resolve correctly at read time.

You did it

You just designed a news feed.

AuthorReaderFeed APISocial GraphFeed CacheFan-out WorkersPost StoreRankingOther SourcesPost Events
The finished design, end to end. · swipe to pan the diagram

Everything you assembled, in order

  • A Feed API over a Post Store; feeds reference posts by ID, never copy bodies.
  • Pull (fan-out on read) is simple and fresh but slow for big follow counts.
  • Push (fan-out on write) precomputes feeds for O(1) reads at write-time cost.
  • A ranking stage orders candidates by affinity, recency and engagement.
  • A hybrid model pushes for normal authors and pulls celebrities to dodge mega-fan-out.
  • Multiple candidate sources (pages, recs, ads) blended under one ranker.
  • Cursor pagination, per-session dedup and ID hydration keep an infinite scroll correct.

Where an interviewer pokes next

Getting the boxes right is the easy half. These are the questions that separate a candidate who drew the diagram from one who has run the thing. Answer each one out loud before you open it.

  1. How fresh is the feed — can a reader miss a just-posted item?

    Briefly, yes. Push is async via the event stream, so there’s a short lag between posting and the ID landing in followers’ caches. Readers tolerate seconds of staleness; for "just posted" immediacy you pull the author’s most recent posts at read time, exactly as you already do for celebrities.

  2. A reader follows 5,000 accounts AND several celebrities — does read stay fast?

    Yes. The 5,000 normal authors were pushed, so they’re a single precomputed lookup; only the handful of celebrities are pulled and merged at read time. The merge set is small regardless of total follow count.

  3. How do you keep ranking from being slow on every read?

    Rank only a bounded candidate window (a few hundred IDs), not all of history. Heavy features are precomputed; the read-time model is light. You can also cache the ranked page behind the cursor so a re-fetch doesn’t re-rank.

  4. A post is deleted after fan-out to a million feeds — now what?

    Nothing to clean up. Feeds store IDs, not bodies, so hydration re-checks the Post Store at read time; a deleted or privacy-changed post simply resolves to nothing and is skipped. The fan-out copies are harmless references.

  5. How do you stop the same post or ad repeating as you scroll?

    Per-session dedup tracks seen IDs against the cursor, and ad-spacing / diversity rules run in the blending stage so sources don’t clump. Cursor pagination guarantees a stable position so inserts never cause dupes or gaps.

Check yourself — the answers, and why

Eight steps in, these are the calls you should be able to make cold. Pick one, then read why.

  1. Feeds store post IDs, not post bodies, mainly so that…

    • Feeds use less RAM
    • Edits/deletes/privacy resolve correctly at read time
    • Posts render faster

    References mean a deleted or edited post is handled at hydration — no fan-out cleanup across millions of feeds.

  2. Fan-out on WRITE (push) makes reads O(1) at the cost of…

    • Stale content
    • Write amplification — one post becomes many cache inserts
    • Losing posts

    One post becomes thousands of cache writes — fine until an author has millions of followers.

  3. Celebrities are handled by…

    • Pushing faster with more workers
    • Pulling their posts at read time (hybrid)
    • Bigger feed caches

    50M cache writes per post is ruinous; pull the few celebrities and merge a tiny set at read time.

  4. A feed splits retrieval from ranking because…

    • It’s easier to code
    • You gather cheap candidates, then a model orders just those
    • Ranking is optional

    Two-stage: fan-out gathers candidates, a model ranks the bounded set — the same pattern as search.

  5. Infinite scroll stays consistent under constant inserts via…

    • Page numbers (?page=2)
    • Cursor-based pagination + per-session dedup
    • Refetching from the top each scroll

    A stable cursor avoids dupes and gaps; dedup stops repeats as new posts arrive up top.

How you’d open this design in an interview

Before any boxes: agree what it must do, pin the qualities that shape everything, then build — naming each trade-off as you make it. The walkthrough above is that exact order.

What it must do

Agree on these before drawing a single box.

  • Post: an author publishes; the body is stored once in the Post Store and referenced by ID.
  • Read a feed: GET /feed returns a reader’s personalized, ranked stream in a few hundred ms.
  • Fan out: push a new post’s ID into every follower’s precomputed feed at write time.
  • Rank: order candidates by affinity, recency, and predicted engagement — not just recency.
  • Mix + paginate: blend friends, pages, recommendations and ads under one ranker, and scroll infinitely without dupes.

The qualities that shape everything

Each one names the mechanism that buys it.

Edits and deletes resolve everywhere for free
Feeds store post IDs, not bodies — one durable copy in the Post Store, hydrated at read time so a deleted or edited post resolves correctly.
Reads are O(1), not a 2,000-way merge
Fan-out on write: workers pre-build each follower’s feed cache, so reading is a single lookup of precomputed IDs.
The best post isn’t buried by the newest
A ranking stage scores candidates by affinity, recency, and predicted engagement — retrieve cheaply, then rank the bounded set.
A celebrity post doesn’t trigger 50M writes
A hybrid model: push for ordinary authors, but skip fan-out for mega-accounts and pull their recent posts at read time.
New content types slot in without a new feed
Every source (pages, recs, ads) is a candidate generator feeding one shared ranker that interleaves under one policy.
Infinite scroll stays consistent under churn
Cursor-based pagination plus per-session dedup, so constant inserts and deletes never cause dupes or gaps.

The trade-offs you say out loud

Senior signal isn’t the boxes — it’s naming what you gave up and why it was the right price.

Reference posts by ID over copying the body into every feed

Duplicated bodies turn every edit or delete into a distributed cleanup across millions of copies. One durable copy hydrated at read time keeps edits, deletes and privacy correct everywhere for free.

Fan-out on write (push) over caching pull results

Caching pull still makes the first reader pay the full 2,000-way merge, cold exactly when new posts arrive. Pre-building each feed moves the work from many reads to one write, so reads are O(1).

Rank by affinity, recency, engagement over strict reverse-chronological

Recency alone lets one chatty account drown the post you care about. Two-stage retrieve-then-rank orders a bounded candidate set by relevance instead of luck and timestamps.

Hybrid push + pull over pushing to all 50M feeds

Pushing a celebrity post is 50M cache writes, much of it for followers who never open the app. Pull the handful of mega-accounts at read time and the merge set stays single-digit — reads fast, writes sane.

Cursor pagination over offset page numbers

When posts arrive at the top, every offset shifts — page 2 repeats or skips items. A stable cursor marks position so a live, churning feed never dupes or gaps.

What this teaches

Learn system design by building a social news feed step by step. An interactive guide covering the social graph, pull vs push fan-out, a precomputed feed cache, ranking, the hybrid model for celebrities, mixing content sources, and pagination.

Key takeaways

  • A Feed API over a Post Store; feeds reference posts by ID, never copy bodies.
  • Pull (fan-out on read) is simple and fresh but slow for big follow counts.
  • Push (fan-out on write) precomputes feeds for O(1) reads at write-time cost.
  • A ranking stage orders candidates by affinity, recency and engagement.
  • A hybrid model pushes for normal authors and pulls celebrities to dodge mega-fan-out.
  • Multiple candidate sources (pages, recs, ads) blended under one ranker.
  • Cursor pagination, per-session dedup and ID hydration keep an infinite scroll correct.

Concepts covered

  • What is a news feed?
  • Post and read
  • Pull (fan-out on read)
  • Push (fan-out on write)
  • Ranking
  • Go hybrid
  • Mixing sources
  • Pagination, dedup & freshness
built to be scrolled, not memorized — make the calls, break fan-out, run the gauntlet.
Finished this one? 0 / 65 System Designs done

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.

More System Designs