← Back to practice catalog

System design interview guide

Facebook Feed System Design

TL;DR:

Your friend posted ten minutes ago but your feed still looks like yesterday— fan-out lag or a slow ranker is the product failure, not a missing database box. Hybrid fan-out, a celebrity policy, and honest degradation when ranking times out are what interviewers grade on a Facebook-style home feed.

Overview diagram for Facebook Feed System Design

Problem statement

You're designing a Facebook-style home feed: posts from people and pages someone follows, ranked or chronological, paginated, and fast to scroll.

Functionally you need create post, follow graph, home feed pages, optional reactions and comments, rank or recency modes, and block or mute. Non-functionally you need roughly sub-300 ms feed p95 for the common path, high availability, and durable posts—while ranking may lag by seconds. Scale sits at hundreds of millions of daily actives with reads far exceeding writes, and a few accounts with follower counts so large that naive fan-out becomes a cost and reliability incident.

What interviewers reward: hybrid fan-out with a celebrity policy; mailboxes of IDs separate from post bodies; bounded candidates and ranker timeouts; cursor pagination with honest dup/skip; degrade ranking—not a blank feed—when dependencies fail.

Introduction

You open the app after lunch. Your friend posted a photo ten minutes ago, but your feed still looks like yesterday. You pull to refresh. Nothing changes. The post “succeeded” for them—your timeline is just behind.

That feeling is the product problem. The interview is the machinery behind it: reads crush writes, a few accounts have massive follower counts, and any design that does unbounded work per swipe or fans out every post to every follower breaks in cost and tail latency before it breaks on the whiteboard.

Interviewers are not grading box count. They want three ideas you can explain in plain language:

  1. Push vs pull vs hybrid — where you pay cost on publish versus on scroll.
  2. Split storage — feed rows are IDs and order; post bodies and media live elsewhere.
  3. Honest fuzz — ranking moves, graphs change, pagination will duplicate or skip sometimes; say that out loud.

Weak answers draw a message queue with no celebrity policy. Strong answers walk one write and one read and name what degrades when the fan-out queue or ranker lags.

If you remember one thing: The home feed is a bounded read path over precomputed candidates—not one giant join on every scroll.

How to approach

Start the way a user experiences the product, not by listing every service name. Spend the first few minutes turning “design Facebook feed” into a contract you can design against. Talk through clarifying questions out loud, then walk one publish and one home page before you name storage brands.

Clarifying questions (say these in the room)

Start with what “feed” means and whether ranking is required, because those answers change fan-out policy and the entire read path.

You: “Is this only the home feed from people and pages I follow, or do we also need groups, pages you do not follow, and ads in the same round?”

Interviewer: “Home feed from follows; ads and groups can stay out of scope.”

That answer keeps you on candidate generation and fan-out instead of building an ads auction on day one.

You: “Is ranking in scope—“Top stories”—or is chronological “Most recent” enough for this interview?”

Interviewer: “Assume a ranked home feed with a fallback to recency.”

Now you know you need a ranker interface with a time budget, not only a mailbox dump sorted by time.

You: “What does fresh mean in seconds—is it okay if friends see a post a few seconds after publish, as long as blocks and safety are correct?”

Interviewer: “Eventual visibility for friends is fine; blocks must not wait.”

That permission lets you async fan-out while still filtering blocks on the hot read path.

You: “Should I treat accounts with tens of millions of followers as a special case, or assume every author is a normal user?”

Interviewer: “Call out the celebrity case explicitly.”

You now owe the room a hybrid policy—not “we fan out to everyone.”

You: “I want to leave full ads ranking, Reels recommendation, and the complete ML training stack out of scope so we can focus on publish, fan-out, home read, and ranker timeouts. Does that match what you want?”

Interviewer: “Yes—focus on home feed at scale.”

Saying out of scope early stops you from spending the round on adjacent products.

Minute pacing (about 45–60 minutes)

MinutesFocus
0–5Clarify home vs ranking, freshness, celebrities, out of scope
5–12Capacity: read:write skew + one celebrity fan-out estimate
12–25Write path + hybrid policy; data model (mailbox vs post)
25–40Read path dig: candidates, hydrate, filter, rank, cursor
40–50Failure / one production scene
50–60Questions / deepen one tradeoff

In the room (a fuller opening you can actually say): “I will design the home feed from follows. Posts become durable first; fan-out to follower mailboxes runs asynchronously with idempotent writes. For normal authors I push; for mega-followed authors I merge on read so I do not write tens of millions of rows per post. On read I load a bounded candidate set of post IDs, batch-fetch bodies, filter blocks, score under a hard timeout with a recency fallback, and return an opaque cursor. Ranking can be seconds stale; empty feed on ranker failure is not acceptable.”

Out of scope (and why you park these)

Write a short out-of-scope list on the board so the interviewer sees you can bound the problem.

Full advertising auction and billing. Ads change ranking and money flows, but they steal the interview from hybrid fan-out and read-path budgets. You can note “ads inject candidates later” without designing the auction.

Training the ranking model end to end. You need the serving interface: candidates in, scores out, timeout behavior. Building feature stores and training pipelines is a different interview.

Groups, Stories, Reels, and Marketplace as full products. Each has its own fan-out and ranking story. Mention them only if the interviewer expands scope.

Strongly consistent worldwide visibility the millisecond someone posts. Home feed almost always accepts short lag. Promise instant global mailbox sync and you invent a harder problem than the room asked for.

Capacity estimation

Before you draw architecture boxes, use rough numbers so you do not promise impossible per-scroll work.

DimensionRough scaleWhat this means for your design
DAUHundreds of millionsHome reads dominate; cache and shard aggressively
Posts per dayHundreds of millions globallyWrite QPS is modest next to read QPS
Follow edgesHighly skewedMedian follows are manageable; celebrities dominate cost
Fan-out for 50M followers50M mailbox writes per post if naiveMust be policy-exempt or partial—async queue alone does not save you
Feed page sizeTens of postsBound candidates before rank; never score the whole graph

Worked skew sketch: If one celebrity posts once and you fan out to fifty million followers, you create on the order of fifty million mailbox inserts for a single click—before media processing or notifications. That is why “always fan out” fails, even with a fast queue.

If you remember one thing: Numbers exist to show skew—reads dominate, celebrities break naive fan-out.

High-level architecture

What breaks if you merge everything

One service that stores full post JSON in every follower’s feed, ranks with no timeout, and blocks create-post until every mailbox is written will choke on celebrity traffic and hang the edge when ML slows down. Logging every ranking feature online into the critical path makes p95 worse without teaching anyone in the room.

What works: IDs on the timeline, bodies elsewhere

Who owns what:

  • API / edge — Auth, rate limits, timeouts to downstreams.
  • Feed service — Orchestrates the read path: candidates, graph checks, hydrate, rank, cursor. This is where you cap work.
  • Mailbox / timeline store — Ordered post IDs (or score+id) per viewer, sharded by user_id.
  • Post service + object storage + CDN — Source of truth for post metadata and media bytes.
  • Graph service — Follow, unfollow, block, mute—cached carefully on the feed path.
  • Fan-out workers — Consume a queue; append to mailboxes where push policy allows; idempotent (viewer_id, post_id).
  • Ranker — Scores a bounded candidate set under a hard time budget.

Celebrity / hybrid on the whiteboard: For authors you do not fully fan out, the feed service merges recent posts by author into the candidate pool. Draw that edge—or you only drew push fan-out and invite the follow-up you deserve.

[ Client ]
    → [ LB / API gateway ] → [ Feed svc ] → [ Mailbox store / celebrity merge ]
                                 |                    ↓
                                 |              [ Ranker + timeout ]
                                 |                    ↓
                                 +-- [ Graph ]   response + cursor
                                 +-- [ Post svc ] ← media via CDN
                                 |
          [ Post create ] → durable post → [ Fan-out queue ] → workers → mailboxes

In the interview: Narrate the read path first (latency budget, bounded candidates, ranker timeout). Then one write (durable post → async fan-out → idempotent mailbox writes). Storage brand names come after the story makes sense.

If you remember one thing: Read path is IDs → batch hydrate → rank with timeout; write path acks before every mailbox row exists.

Core design approaches

Fan-out on write (push)

After a post is stored, push its ID into each follower’s mailbox. Reads feel cheap because the heavy work already happened.

The catch is the O(followers) wall. The moment you say “we fan out to everyone,” you owe the room a celebrity exception—or you have designed a machine that spends your cloud budget as a distributed write storm.

Pull on read

At request time, pull recent posts from followed accounts and merge. That dodges the celebrity write blast, but you can spend a lot of CPU merging when someone follows thousands of accounts—so real systems cap, cache, or hybridize.

Hybrid (what production usually sounds like)

PolicyWhen it fitsCost you accept
Push to follower mailboxesLong-tail authors (modest follower counts)Storage and fan-out CPU on publish
Merge / pull recent by authorCelebrities and mega-pagesExtra work on the home read path
Partial fan-out to active usersMiddle tier or “online now” optimizationStale mailboxes for inactive viewers

Push for the long tail. For mega-followed authors, do not materialize every edge. The exact threshold matters less than saying there is a policy and naming the cost driver (queue depth, storage, blast radius).

If you remember one thing: Hybrid is the real answer—pure push or pure pull alone fails at this scale.

Data model

Keep three ideas separate: what each viewer scrolls, what a post is, and who can see whom.

Mailbox / timeline (per viewer)

Field / conceptWhy it exists
viewer_idShard key for that person’s home timeline
post_idPointer into the post store—not the full body
score or created_atOrdering hint for recency or last known score
author_idHelps celebrity merge and filter
Idempotency on (viewer_id, post_id)Retries must not duplicate rows

Posts and media

ConceptStoreNote
Post metadataPost service / DBAuthor, text, privacy, timestamps, media keys
Media bytesObject storage + CDNUpload before or beside create; feed path only carries URLs or ids
Author profile cacheCache / profile svcSafe to be slightly stale for display names

Graph

EdgeHot-path rule
FollowDrives fan-out membership and pull-merge sets
Block / muteMust filter on read even if mailboxes lag
UnfollowMay purge asynchronously; filter until purge completes

Interview land: Draw “mailbox = ordered IDs” and “post store = bodies” as two boxes. One database that stores full JSON in every follower row is the anti-pattern.

Detailed design

Tell the story like an outage retro for one post and one scroll—that is how interviewers decide whether you understand the product clocks.

Write path

When someone publishes, large media should already be landing in object storage (or uploading in parallel), while the post service writes the durable metadata: author, text, privacy, media ids, timestamps. The create API returns success once that metadata is safe. It does not wait until every follower’s mailbox row exists—that wait is how celebrity posts time out.

Fan-out then runs asynchronously: workers append the post id into follower mailboxes where hybrid policy allows push, using an idempotent key so retries do not duplicate entries. Search indexing, notifications, and link previews can trail afterward. If you put those on the critical create path, you miss latency targets and still sometimes generate the wrong preview image.

Read path

Scrolling home is a different budget. Load a bounded chunk of candidate post ids for this viewer—usually from a precomputed mailbox, plus any celebrity merge-on-read. Batch-fetch the post bodies and author cards for those ids only. Apply block and hard safety filters here even if an old id still sits in a mailbox. Then score under a hard time budget; if the ranker is late, return a recency-ordered or last-good slice instead of hanging the app. Finish with an opaque cursor so the next page can continue when ranks move between requests.

If your whiteboard answer stops at “we call the ML service,” the follow-up will be: what happens when that service is slow? Strong answers already have the timeout and fallback in the read story.

In the room (spoken): “Create returns after durable metadata; fan-out catches up asynchronously with hybrid policy for big authors. Home scroll loads capped ids, hydrates in batch, filters blocks, ranks with a timeout, and returns a cursor—post 201 and ‘friend sees it’ are two different clocks.”

Architectural dig: one home-feed page (and one celebrity publish)

High-level boxes showed ownership. This dig is how scroll stays fast when a celebrity posts and when the ranker misbehaves.

1) Publish: durable post, then policy-aware fan-out

Responsibility: Post service owns durability and identity (post_id). Fan-out workers own mailbox appends where push is allowed. Feed service must not wait on millions of inserts before returning 201.

  1. Validate author and content policy (light checks on create).
  2. Persist post metadata; associate already-uploaded media_ids if any.
  3. Enqueue fan-out job { post_id, author_id, follower_tier_policy }.
  4. Workers expand followers (or skip full expand for celebrity tier) and write idempotent mailbox rows.

2) Celebrity blast radius (bad vs great)

Bad design: always push to every follower

A page with fifty million followers hits Post. Workers attempt fifty million mailbox writes. The fan-out queue ages; friends’ feeds look stale for minutes while create-post dashboards stay green.

Post 201 ──► enqueue fan-out ──► 50M mailbox writes
                │
                └── queue age ↑  while API success looks fine

Great design: hybrid policy by follower tier

Classify the author. Long-tail: push. Mega-followed: store in an author-indexed recent list and merge on read into each viewer’s candidate set (optionally push only to recently active viewers).

Celebrity publish: naive fan-out writes tens of millions of mailbox rows; hybrid policy pushes for the long tail and merges mega-authors on read

Figure: Follower count picks whether you pay on publish or on scroll. Pure push to everyone is a cost and lag incident waiting to happen.

Scale inside the box: Monitor queue age, writes per shard, and time-to-first-visibility for sampled posts—not only create 201 rate.

Failure inside the box: If workers die mid-fan-out, idempotent retries finish the long tail; celebrity merge still lets actives see content from the author store.

3) Read: bounded candidates under a rank budget

  1. Authn viewer; load block/mute set (cache with strict freshness for blocks).
  2. Read mailbox head (and merge celebrity tails) → cap N candidates (for example a few hundred, not “everyone you follow forever”).
  3. Batch-get posts + authors; drop tombstones and blocked authors.
  4. Call ranker with deadline T ms; on timeout use recency or last known order.
  5. Return page of size K + opaque next_cursor.

Interview land: “I never let ranking see an unbounded set, and I never let ranking own the edge’s thread pool without a timeout.”

4) Pagination when scores move

Between page 1 and page 2, ranks and new posts arrive. Offset/limit skips and duplicates badly. Prefer an opaque cursor that encodes enough to continue (session snapshot or (score, post_id)). Admit best-effort stability: clients should skip duplicates; rare skips are okay.

5) Numbered happy path (put it together)

  1. Create post → durable post_id → 201.
  2. Fan-out (or celebrity skip) → mailbox IDs where policy allows.
  3. Home GET → candidates → hydrate → filter → rank or fallback → cursor.
  4. Next page uses cursor; graph filters still applied.

If you remember one thing: Success on create and a fresh feeling feed are two different SLOs.

Key challenges

ChallengeWhat users see if it goes wrongWhat to say in the interview
Celebrity fan-outFriends’ feeds stuck while posting still “works”Hybrid policy; queue age alerts; merge on read
Moving ranksDuplicate posts or gaps while scrollingOpaque cursors; admit best-effort dup/skip
Graph churnBlocked user still appears; unfollow hangsFilter blocks at read; async purge / TTL
Ranker lagSpinners or empty feedTimeout + recency fallback; circuit breaker
Hot post cache stampedeOne viral ID melts post storeSingleflight, TTL jitter, watch origin QPS per key

If you remember one thing: Skew picks fan-out policy; moving rank picks cursor honesty.

Scaling the system

Shard mailboxes by viewer_id. Shard posts by id or author-time. Avoid multi-table joins on the hot home path—hydrate by id batch.

Cache hot post bodies, profiles, and following-set snapshots. Use TTL jitter and request coalescing so one viral post_id does not align every miss.

Multi-region: Prefer local reads with eventual fan-out replay. Do not claim one globally strongly consistent mailbox view unless the interviewer forces that harder problem.

Cap pull-merge fan-in when someone follows thousands of accounts—otherwise hybrid still burns CPU on read.

If you remember one thing: Scale reads with sharded mailboxes + CDN; scale writes with async fan-out + celebrity caps—not bigger SQL joins.

Failure handling

ScenarioWhat the user seesWhat to build
Ranker slow or downSpinners or empty homeHard timeout; recency fallback; feature-flag heavy models
Fan-out backlogPost succeeded; friends see stale homeAlert on queue age; lean on merge-on-read; priority lanes
Cache stampede on hot postp99 spike on one IDSingleflight; stale-while-revalidate; jittered TTL
DB / post store degradedErrors or blank cardsCircuit break; serve stale-but-safe slices where product allows

If you remember one thing: Degrade ranking (recency, stale slice)—do not block the edge forever behind a slow ranker.

API design

Illustrative REST-style surface (GraphQL is fine if you name batching and field cost—feeds are where naive graphs hurt).

POST   /v1/posts
GET    /v1/me/home
GET    /v1/posts/{post_id}
POST   /v1/users/{user_id}/follow
DELETE /v1/users/{user_id}/follow

Home feed — GET /v1/me/home

Query paramRole
cursorOpaque continuation (preferred)
limitPage size (cap server-side, e.g. ≤ 50)
rankingtop or recent
session_idOptional session snapshot for experiments

Response sketch: { "items": [ Post ], "next_cursor": "...", "has_more": true }.

Errors: 401 unauthenticated; 429 with Retry-After when throttled. Avoid leaking whether a blocked user exists—use generic 404/403 per product policy.

Create post — POST /v1/posts

Use an Idempotency-Key so mobile retries do not create duplicate stories. Body carries text and media_ids[] already uploaded via separate upload URLs—do not put video bytes in JSON. Success is 201 with post_id and a processing state for media (pending / ready).

Follow graph

POST / DELETE follow return quickly. Graph updates are eventually visible in feed—say so if asked. Blocks remain a read-path safety filter regardless.

Cross-cutting behavior to name in the interview

  • Rate-limit create and follow separately from home read.
  • Document cursor opacity and moving-rank semantics.
  • Keep reactions/comments off the feed p95 critical path unless scoped in.

In the interview: One minute on idempotent create, cursor semantics for home, and why ranking is not allowed to hang the gateway is enough to sound shipped—not memorized.

Observability (what you measure)

SignalWhy it matters
Post create success vs fan-out queue ageExplains “posted but friends don’t see it”
Time-to-first-visibility (sampled)Product freshness SLO
Ranker p99 + timeout / fallback rateSeparates rank health from feed availability
Candidates scored per requestCatches unbounded merge
Origin QPS per hot post_idStampede detection
Empty feed / 5xx rateUser-visible outages

Green create rates alone will lie while timelines feel stale.

Security and abuse

Authenticate every home and create call. Authorize visibility (friends-only, public, blocked) on read, not only at fan-out time. Rate-limit post create, follow, and react to slow spam and follow-bots. Treat ranking logs carefully—do not dump private post bodies into unrestricted analytics without access control. Abuse and integrity pipelines (fake engagement, coordinated amplification) belong beside the feed, not as an afterthought that rewrites every mailbox synchronously.

Cost awareness

Every pushed mailbox row costs storage and write IOPS forever (or until TTL). Celebrity push-to-all is a cloud bill incident, not a clever scale story. Scoring huge candidate sets burns CPU on every scroll. CDN and object storage dominate media cost; keep blobs off the mailbox path. Caching reduces post-store load but multiplies complexity—buy cache where keys are hot and stamps are measurable. Choose explicitly whether you spend money on precompute storage or read-time merge CPU.

When users are stuck but the dashboards look fine

Textbooks teach boxes and arrows. On-call teaches this: post create can look healthy while the home feed feels stuck in yesterday.

Three nightmares that look fine in the middle:

What the dashboard showsWhat is actually happening
Post create 201 rate is green.Fan-out queue age is climbing; friends refresh and see old stories.
Ranker error rate is low.Ranker p99 ate the gateway thread pool; feeds hang without many 5xx.
Cluster CPU looks calm.One viral post_id is stampeding the origin after a synchronized TTL expiry.

Scene 1: Fan-out backlog while posts “succeed”

The moment: A live event or celebrity posts. Create still works. Friends refresh and still see yesterday’s top of feed.

The trap: Fan-out is async. Workers append at finite speed. Dashboards that only chart create success hide time-to-visible.

What to build: Alert on queue age and per-shard backlog. Cap fan-out per tick; lean on read-side merge while the queue drains. Priority lanes for recent posts vs backlog drain.

Scene 2: Ranker deploy hangs the feed

The moment: After a ranking release, homes spin; unrelated routes feel slow.

The trap: Ranker sits on the hot path without isolation. Missing timeout fills the edge thread pool.

What to build: Hard rank timeout; circuit breaker; recency fallback; kill switch for heavy models. Separate SLOs: feed loads vs perfect rank.

Scene 3: “I see it, you don’t”

The moment: Coworkers disagree whether a viral post appeared.

The trap: Global fan-out is not one transaction. Regional shards and at-least-once workers mean eventual visibility.

What to build: Idempotent mailbox writes; dashboards on cross-region lag. Do not promise instant worldwide materialization.

Scene 4: Cache stampede on a hot post ID

The moment: One viral post; feed still loads but p99 spikes; post service catches fire while “average cache hit ratio” looks fine.

The trap: Every scroll multi-gets the same post_id. Aligned TTL expiry creates a miss herd.

What to build: Singleflight per key; TTL jitter; stale-while-revalidate; watch origin QPS on one key, not only cluster CPU.

In the interview: Pick one scene. Tell what users felt, which metric lied, and what you would ship next.

Bottlenecks and tradeoffs

Precompute vs read-time merge

The tension — Materializing every follower’s mailbox makes scroll fast; celebrities make write amplification impossible.

What breaks — Fan-out queue depth explodes; one post fans out to tens of millions of rows.

What teams do — Hybrid: push for normal accounts, merge on read for the head; alert on queue age.

Say in the interview — Name who you fan out to and who you merge at read—not “we fan out.”

Fresh ranking vs stable pagination

The tension — Users want relevant order; cursors want stable continuation.

What breaks — Duplicates or skips when scores shift between page loads.

What teams do — Opaque cursors, session snapshots, client-side dup skip; admit best-effort.

Say in the interview — Offset/limit at scale is a trap; cursor + honesty beats fake consistency.

Cost vs freshness

The tension — More precomputed mailboxes smooth reads; they cost storage and fan-out CPU.

What breaks — Thin mailboxes push merge work into p99 read when someone follows thousands of accounts.

What teams do — Cap candidates before rank; TTL trim on mailboxes; tier storage for cold tails.

Say in the interview — Pick what you buy with money: storage or read CPU.

If you remember one thing: Every feed tradeoff is where you pay—publish, scroll, or ops when queues lag.

Interview tips

You have the full design in mind now. These five back-and-forths are how interviewers test whether you can defend it under pressure. Each one starts with a tempting shortcut, an interview push, and a clear answer.

Fan-out on write only — celebrities melt the queue

You might say: “When someone posts, we fan out to every follower’s mailbox.”

Interview Push: “A page with 50 million followers hits Post—what happens to your queue and storage?”

Land here: That is on the order of fifty million mailbox writes for one click if you are naive. Use a hybrid policy: push for the long tail where fan-out is cheap; for mega-followed authors, merge on read, partial fan-out to active users, or store by author and intersect at scroll time. Name queue depth and blast radius, not only “we use Kafka.” If create returns 201 while queue age climbs, friends’ feeds still look stale—and that is an ops story you should volunteer.

Where post bodies live — pointers on the timeline

You might say: “The feed service stores everything in one database.”

Interview Push: “What travels on every scroll—full post JSON or pointers?”

Land here: The mailbox / timeline store holds ordered post IDs (or score+id) per viewer, sharded by user_id. The post service plus object storage and CDN own bodies and media. The feed path multi-gets by id and caps work. Shipping full bodies in every follower row multiplies storage and makes edits and deletes painful.

Ranking as one box — timeouts beat perfect scores

You might say: “We call the ML service and sort.”

Interview Push: “Ranker p99 doubles—does the whole app hang?”

Land here: Separate candidate generation (bounded list of IDs) from scoring. Put a hard timeout on rank; fall back to recency or the last good slice. Add a circuit breaker so the edge does not block on one dependency. Perfect ranking that empties the feed is a product failure, not a win.

Pagination with moving order — cursors over offsets

You might say: “We use offset and limit—page 2 is easy.”

Interview Push: “Scores change between requests—do users see duplicates or gaps?”

Land here: Use an opaque cursor or (score, post_id) continuation. Admit best-effort stability—rare duplicates or skips—rather than fake strong consistency. Offset pagination at feed scale is a trap because the list underneath the offset keeps moving.

Blocks and unfollows — safety now, purge later

You might say: “We delete all feed rows when someone unfollows.”

Interview Push: “At a billion edges, can you recompute every mailbox synchronously?”

Land here: Graph updates are eventual for unfollow. Filter blocks at read for safety even if a stale ID still sits in a mailbox. Use TTL, lazy filter, or compensating deletes for soft graph churn. Brief unfollow staleness is usually okay; block paths are not.

Red flags to avoid without correcting yourself: “Fan out to everyone,” “offset pagination,” “rank with no timeout,” “one DB holds full posts in every feed,” “recompute all mailboxes on unfollow.”

After each interview push, close with one real part of the design you would build—hybrid threshold, idempotent (viewer_id, post_id), ranker timeout, or opaque cursor—not “we’ll scale it later.”

What should stick

After reading this guide, you should be able to explain:

  1. Read:write skew — Almost everyone scrolls; few post; celebrities break naive fan-out.
  2. Hybrid fan-out — Push where cheap; merge or pull for the head; policy by follower count.
  3. IDs vs bodies — Mailboxes hold order; posts and media live elsewhere; batch hydrate.
  4. Ranker is best-effort — Bounded candidates, timeout, recency fallback—never block the edge.
  5. Cursors over offsets — Moving rank means honest dup/skip, not fake strong consistency.

Tell it in the room: “Home feed: durable post, async idempotent fan-out to shards where policy allows, read path loads capped candidate IDs, multi-gets bodies, filters blocks, ranks with a timeout, returns a cursor. Celebrity: no O(followers) write—merge on read. When fan-out lags, users still scroll stale mailboxes; when ranker lags, fall back to recency.”

Key Takeaways

  • Clarify first — Home vs ranking, freshness seconds, celebrity policy, out of scope.
  • Hybrid fan-out — Push the long tail; merge mega-authors on read.
  • Split storage — Mailboxes store IDs; posts and media live elsewhere.
  • Bound the read path — Cap candidates; hydrate in batch; filter blocks; rank with a deadline.
  • Degrade ranking, not the feed — Recency fallback beats empty spinners.
  • Honest cursors — Moving scores mean occasional dup/skip; offsets lie.
  • Operate queue age and hot keys — Create 201 can look fine while timelines feel stale.

Quick revision notes

Use this as a last look before a mock interview, not as a substitute for the full guide.

Clarify first. Agree home-only scope, whether ranking is required, how many seconds of freshness friends can tolerate, that celebrities need a special policy, and what you leave out (ads ML train, Reels). Skipping this often means you draw Kafka with no cost story.

Pay on publish or on scroll—pick by follower tier. Push mailbox IDs for normal authors. For mega-followed authors, merge recent posts on read so one publish does not become tens of millions of writes.

Keep the timeline thin. Mailboxes store ordered IDs. Post bodies and media hydrate in batch. Ranking scores a bounded set under a timeout and falls back to recency when the model is slow.

Paginate honestly. Opaque cursors beat offsets when ranks move. Blocks filter on read even if unfollow cleanup is eventual.

Operate the lag. Alert on fan-out queue age, ranker timeouts, and hot post_id origin QPS—because green create rates and an angry “my feed is stuck” can coexist.

Practice this path: Facebook Feed System Design.

What interviewers expect

  • Hybrid fan-out: push for the long tail; merge or pull for mega-followed authors.
  • Split storage: mailboxes hold ordered post IDs; post bodies and media live elsewhere.
  • Bounded read path: candidates → batch hydrate → safety filters → rank with timeout → cursor.
  • Ack before full fan-out: post create succeeds when metadata is durable; followers catch up async.
  • Degrade ranking, not the feed: recency fallback when the ranker is slow.
  • Honest pagination: opaque cursors; occasional duplicates or skips when ranks move.

Interview workflow (template)

  1. Clarify requirements. Confirm functional scope, users, consistency needs, and which non-functional goals matter most (latency, availability, cost).
  2. Rough capacity. Estimate QPS, storage, and bandwidth so your data model and partitioning story are grounded.
  3. APIs and core flows. Define a minimal API and walk 1–2 critical read/write paths end to end.
  4. Data model and storage. Choose stores for each access pattern; call out hot keys, indexes, and retention.
  5. Scale and failure. Add caching, sharding, replication, queues, or fan-out as needed; say what breaks in failure modes.
  6. Tradeoffs. Name alternatives you rejected and why (e.g. strong vs eventual consistency, sync vs async).

Frequently asked follow-ups

  • Fan-out on write vs pull on read vs hybrid?
  • How do you handle 50 million followers?
  • What happens when the ranker is slow?
  • How do you paginate when scores change?
  • What do you alert on when posts succeed but feeds feel stale?

Deep-dive questions and strong answer outlines

Walk through a normal user publishing one post.

Persist post metadata (and media via a separate upload path). Return success once the post is durable—do not wait for every follower mailbox. Enqueue async fan-out with idempotent writes keyed by (viewer_id, post_id). Long-tail followers get mailbox appends; mega-followed authors follow the celebrity policy (skip full fan-out, merge on read). Offload search index, notifications, and link previews after the post row exists.

How do celebrity accounts change the write path?

Do not materialize O(followers) mailbox rows for tens of millions of edges. Mark the author for hybrid policy: store by author, fan out only to active viewers, or merge recent posts on read into each home candidate set. Say the cost drivers—queue depth, storage, blast radius—not only “we use Kafka.”

Walk through reading one page of the home feed.

Load a bounded set of candidate post IDs from the viewer mailbox plus any celebrity merge. Batch-get post bodies and authors. Filter blocks and hard safety rules. Score under a hard timeout (or fall back to recency). Return items plus an opaque next_cursor. Cap candidates so p95 stays in budget.

What if the ranker p99 doubles after a deploy?

Hard timeout on ranking; circuit breaker; return a recency-ordered slice or last good candidate order. Separate SLOs for “feed loads” vs “perfect rank.” Do not let the API gateway thread pool block forever on one dependency.

Someone unfollows or blocks—how does the feed update?

Blocks must be enforced at read for safety (cached block list is fine if fresh enough). Unfollow can be eventual: filter at read, TTL stale mailbox entries, or run compensating deletes asynchronously. Do not recompute every mailbox synchronously at a billion edges.

AI feedback on your design

After a practice session, InterviewCrafted summarizes strengths, gaps, and interviewer-style expectations—similar to a written debrief. See a static example report, then practice this problem to get feedback on your own answer.

FAQs

Q: How deep into ML ranking do I need to go in a system design interview?

A: Usually you describe the interface—inputs (candidate IDs, features), a time budget, and what happens on timeout—not training pipelines. Name freshness SLAs and a recency fallback. If they push on models, keep one sentence on features and return to fan-out and pagination.

Q: Is fan-out on write enough by itself?

A: Pure push works for modest follower counts and fails for celebrities. Pure pull works for mega-authors and can burn CPU when someone follows thousands of accounts. Strong answers name a hybrid policy with an explicit threshold or author tier.

Q: Do feeds need strong consistency across every follower instantly?

A: Usually no. Seconds of lag after publish are acceptable for home feed. Blocks and hard safety are stricter—filter at read even if mailboxes lag. Say the consistency bar out loud so you are not promising a global atomic fan-out.

Q: How is a news feed different from a chat product like WhatsApp?

A: Feeds optimize read fan-out, ranking, and scroll latency. Chat optimizes per-thread order, delivery receipts, and often strong privacy. Feeds tolerate brief staleness; chat users notice hundreds of milliseconds. See WhatsApp System Design for the messaging contrast.

Q: Why not offset/limit pagination for home feed?

A: Rankings move between requests. Offsets skip or duplicate as items shift. Opaque cursors (or score+id continuations) plus client-side duplicate skip are the honest contract at scale.

Q: What should I alert on in production?

A: Fan-out queue age and per-shard backlog, ranker p99 and timeout rate, time from post create to first mailbox visibility for sampled authors, cache origin QPS on hot post IDs, and feed empty-error rate—not only post create 201s.

Practice interactively

Open the practice session to use the canvas and stages, then review AI feedback.