Social Feed Ranking System Design

A system design interview walkthrough for a ranked social feed at 500M daily active users — fanout-on-write vs. fanout-on-read, the celebrity-account problem, and how ranking actually happens at serve time.

Rahul Bisht

Founder, CrawlPilot

·
Aug 18, 2026
·System Design·
10 min read
·
Social Feed Ranking System Design

A social feed looks like a sorted list, but it's really two different hard problems wearing one UI: getting the right candidate posts in front of a ranking step fast enough, and doing that for both a user with 12 followers and one with 50 million, without treating them identically. This post walks through the design the way an interview conversation actually unfolds.


Requirements and Goals of the System

Functional Requirements

  • Show a personalized feed of posts from accounts a user follows, ranked by relevance rather than pure chronology
  • A new post should become eligible to appear in followers' feeds within seconds of being created
  • Handle accounts with wildly different follower counts (a few dozen vs. tens of millions) without one degrading the system for everyone
  • Incorporate engagement signals (likes, comments, shares) into future ranking

Below the line (out of scope)

  • Post creation and media upload pipeline — assume a post already exists with its metadata by the time this system sees it
  • Comment storage/threading — a related but separate data model
  • Ad insertion into the feed — a separate system that reserves slots; ranking organic content is enough of a problem on its own

Non-Functional Requirements

  • Scale: ~500M daily active users, each checking their feed several times a day — call it ~2.5 billion feed reads/day
  • Latency: a feed should load in well under 200ms
  • Freshness: new posts should be eligible to appear within seconds, not minutes
  • Consistency: eventual consistency is fine — nobody notices or cares if a brand-new post takes a few seconds to reach every follower's feed

Capacity Estimation and Constraints

Reads: ~2.5 billion feed loads/day averages to roughly 29,000 reads/second, with normal daily peaks a few times higher.

Writes: if ~10% of 500M users post at least once a day, that's ~50M posts/day, or ~580 posts/second on average — two orders of magnitude less than reads. This read-heavy skew is exactly why precomputing feeds ahead of time (below) is worth the extra write-side complexity: it trades a small amount of work at low-frequency write time for a large amount of savings at high-frequency read time.

Fanout volume: the number that actually varies wildly. An average user with ~300 followers generates ~300 feed-cache writes per post. A single account with 50 million followers generates 50 million — nearly six orders of magnitude more than the typical case from one post. Any capacity plan built around "the average post" will be blindsided by the accounts nowhere near average, which is the whole reason this system needs two different strategies rather than one.


System APIs

http
POST /v1/posts { "author_id", "content" } → { "post_id" } GET /v1/feed?user_id={id}&cursor={c} → { "posts": [...], "next_cursor" }

High-Level Design

The core requirement to design around: serve a fast, ranked, fresh feed to hundreds of millions of users, without one heavily-followed account breaking the system.

Bad solution: compute the feed at read time — on every feed load, fetch recent posts from everyone the user follows, rank them, and return the top results.

This is simple to reason about and immediately too slow at scale: a user who follows a few hundred accounts triggers a scatter-gather query across all of them, re-ranked from scratch, on every single feed open — including the common case where nothing new has happened since their last check five minutes ago.

Good solution: precompute each user's feed ahead of time. When someone posts, immediately push (fan out) that post into the feed cache of every one of their followers. Reading a feed becomes a fast lookup against one already-populated, already-ranked cache instead of a live aggregation.

This makes reads fast for the common case, and creates the problem named above: an account with 50 million followers triggers 50 million fanout writes from a single post — a massive, bursty write spike that dwarfs the typical case by nearly six orders of magnitude, and much of that fanout work is wasted on followers who may not open the app again for days.

Great solution: a hybrid, threshold-based fanout. For accounts under some follower-count threshold (the vast majority), fan out on write exactly as above — fast, cheap, bounded. For accounts above the threshold (celebrities, large publishers), skip write-time fanout entirely; instead, a follower's feed read merges their precomputed feed cache with a lightweight, live lookup against just the small number of celebrity accounts they follow. This bounds the worst-case write spike to a small, known set of high-follower accounts, while keeping the overwhelming majority of reads served from a fast, precomputed cache.


Database Design

  • User — the account; also the node in the social graph
  • Post — content, author, created timestamp
  • Follow — the relationship graph: who follows whom
  • FeedEntry — a precomputed row in a specific user's feed cache: which post, what score, when it was added
  • EngagementEvent — a like/comment/share on a post, the raw signal ranking is trained and refreshed on

The modeling choice worth explaining if asked: FeedEntry is a derived, rebuildable projection — not the source of truth. If a feed-cache shard is lost, it can be reconstructed from Post and Follow (and, for celebrity accounts, the Celebrity Post Index), the same way the fraud post's behavioral profile or the chat post's presence data are rebuildable caches rather than irreplaceable records. Post and Follow, by contrast, are the actual durable data — losing either is a real content-loss incident, not a cache miss.


Detailed Component Design

How does ranking actually work, beyond just recency?

Ranking blends several signals — recency, predicted engagement (a model's estimate of how likely this user is to like/comment on this post), and relationship strength with the author — rather than sorting by a single fixed formula. The practical way this scales is splitting the work into two stages: cheap candidate generation (pull the last N posts from the feed cache and celebrity merge — the "what could possibly appear" set, already bounded to a few hundred items) followed by a more expensive re-ranking pass applied only to that small candidate set. Scoring every post on the platform for every user with the expensive model would never scale; scoring a few hundred pre-filtered candidates per feed load does.

How do new users or new posts get ranked with no history to go on?

A brand-new post has no engagement signal yet, and a brand-new user has no follow graph or engagement history to personalize against — both are cold-start cases. The common approach is to fall back to a coarser signal (topic or account popularity) until enough real signal accumulates, and to treat a slice of ranking as deliberate exploration — occasionally surfacing something outside a new user's known preferences specifically to gather signal, rather than only ever exploiting what's already known.

How do we keep new posts showing up within seconds, given async fanout?

Fanout happens through a queue rather than synchronously in the post-creation request, which means the "within seconds" freshness requirement is really a queue-lag requirement. Fanout workers should be prioritized and autoscaled independently from other background work, and normal-account fanout (fast, bounded per post) should be processed ahead of celebrity-merge computation (which happens at read time anyway, so it isn't competing for the same queue).


Fault Tolerance and Replication

FailureImpactResponse
Feed cache shard lossAffected users see an empty or stale feedRebuildable from Post + Follow (and the celebrity index) — a real but recoverable incident, not data loss, since the cache was never the source of truth
Fanout queue backlogNew posts take longer than expected to reach followers' feedsWorkers autoscale on queue depth; normal-account fanout is prioritized over lower-urgency background recomputation
Celebrity Post Index unavailableFollowers of celebrity accounts temporarily miss those posts in their feedFeed Service degrades gracefully — serves the precomputed cache alone rather than failing the whole feed request
Post Service database write failureRisk of losing a post outrightPost is durable, replicated data (unlike the feed cache) — this store uses synchronous replication across availability zones, since losing a post is a genuine content-loss incident

Extended Requirements

Observability & Monitoring

SignalWhy it mattersAlert on
Feed load latency (P99)Directly user-facingSustained P99 above ~200ms
Fanout queue lagDrives how "fresh" the freshness requirement actually is in practiceLag exceeding a few seconds for normal-account fanout
Celebrity-merge latency at read timeThis path adds work at read time rather than write time — it needs its own budgetSustained rise vs. baseline
Ranking model score distributionFlags the ranking model behaving unexpectedly (e.g., over-favoring one content type)Meaningful drift vs. training distribution

Security & Compliance

Feed ranking has to respect the same visibility rules as the rest of the platform — a private account's posts, or posts from someone who has blocked the viewer, must never surface in a feed regardless of how well they'd otherwise score, which means visibility filtering has to happen before or alongside ranking, not as an afterthought. Ranking also has real content-integrity stakes: a model that optimizes purely for predicted engagement can inadvertently amplify sensational or policy-violating content, so ranking pipelines typically need an explicit integrity/trust-and-safety signal folded in as a down-ranking or exclusion input, not just an engagement score.


Leveled Expectations

Mid-level: Lands on fanout-on-write as an improvement over read-time computation, generally with some prompting toward why read-time ranking doesn't scale.

Senior: Independently identifies the celebrity/hot-user fanout problem before being prompted, and proposes a follower-count-based hybrid strategy; separates the feed cache (rebuildable) from posts and the follow graph (durable) correctly.

Staff+: Frames ranking as a two-stage candidate-generation-then-rerank pipeline rather than a single sort; raises cold start and content-integrity concerns unprompted; reasons about fanout-queue prioritization as the actual mechanism that determines real-world freshness, not just a background implementation detail.


Further Reading