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.
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. Neither problem is "sorting." Both get harder at scale in ways that have nothing to do with each other.
What the Feed Has to Guarantee
Show a personalized feed ranked by relevance, not pure chronology; make a new post eligible to appear in followers' feeds within seconds; handle accounts from a few dozen followers to tens of millions without one degrading the system for everyone; fold engagement signals (likes, comments, shares) into future ranking. Out of scope: the post-creation/media-upload pipeline (a post already exists with metadata by the time this system sees it), comment storage/threading, and ad insertion (a separate system reserving its own slots).
At ~500M daily active users checking their feed several times a day (~2.5 billion feed reads/day, ~29,000 reads/second average) against ~10% of users posting daily (~580 writes/second average), reads outnumber writes by two orders of magnitude — which is exactly why it's worth paying extra complexity at low-frequency write time to make high-frequency read time cheap. Eventual consistency is fine throughout: nobody notices if a brand-new post takes a few seconds to reach every follower's feed. A feed should load in well under 200ms.
Problem One: Getting Candidates to the Reader Fast
Computing the feed at read time — on every load, fetch recent posts from everyone the user follows, rank them, return the top results — is simple to reason about and immediately too slow at scale: a user following a few hundred accounts triggers a scatter-gather query across all of them, re-ranked from scratch, every single time they open the app, including the common case where nothing new has happened since five minutes ago.
Precomputing each user's feed ahead of time fixes the read side: when someone posts, immediately fan that post out into the feed cache of every one of their followers. Reading becomes a fast lookup against an already-populated, already-ranked cache instead of a live aggregation.
Problem One, Continued: The Celebrity Account Breaks the Pattern
Fanout volume is the number that varies wildly, and it's why "just fan out on write" isn't the whole answer. 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" gets blindsided by the accounts nowhere near average.
The fix is a hybrid, threshold-based fanout: accounts under some follower-count threshold fan out on write exactly as above — fast, cheap, bounded. Accounts above the threshold (celebrities, large publishers) skip write-time fanout entirely; a follower's feed read instead merges their precomputed 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 accounts, while keeping the overwhelming majority of reads served from a fast, precomputed cache.
Problem Two: Ranking Is Not Sorting
Ranking blends several signals — recency, predicted engagement (a model's estimate of how likely this user is to like or 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.
Problem Two, Continued: Cold Start
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.
Freshness Is a Queue-Lag Problem in Disguise
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).
Posts, Follows, and the Cache in Between
- 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). Post and Follow, by contrast, are the actual durable data — losing either is a real content-loss incident, not a cache miss.
The Ways This Fails
| Failure | Impact | Response |
|---|---|---|
| Feed cache shard loss | Affected users see an empty or stale feed | Rebuildable 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 backlog | New posts take longer than expected to reach followers' feeds | Workers autoscale on queue depth; normal-account fanout is prioritized over lower-urgency background recomputation |
| Celebrity Post Index unavailable | Followers of celebrity accounts temporarily miss those posts in their feed | Feed Service degrades gracefully — serves the precomputed cache alone rather than failing the whole feed request |
| Post Service database write failure | Risk of losing a post outright | Post 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 |
Keeping Ranking Honest in Production
| Signal | Why it matters | Alert on |
|---|---|---|
| Feed load latency (P99) | Directly user-facing | Sustained P99 above ~200ms |
| Fanout queue lag | Drives how "fresh" the freshness requirement actually is in practice | Lag exceeding a few seconds for normal-account fanout |
| Celebrity-merge latency at read time | This path adds work at read time rather than write time — it needs its own budget | Sustained rise vs. baseline |
| Ranking model score distribution | Flags the ranking model behaving unexpectedly (e.g., over-favoring one content type) | Meaningful drift vs. training distribution |
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.
What Separates the Levels Here
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
- Instagram Engineering: Powering an Personalized Feed at Scale (feed ranking retrospectives)
- Twitter/X Engineering: The Home Timeline Architecture (fanout and timeline mixing)
- Meta AI: Deep Learning Recommendation Models (candidate generation and ranking)
- Alex Xu — System Design Interview Vol. 1 (chapter on news feed systems)
