Meta (Facebook) News Feed System Design Interview: Fanout, Feed Ranking, and the Celebrity Problem
Facebook served around 2.11 billion daily active users out of roughly 3.07 billion monthly actives in 2024 (company-reported), and its News Feed ranks more than 1,000 candidate posts per user, per day on average before showing you a handful. The social graph behind it runs on TAO, which Meta has said handles on the order of a billion reads and millions of writes per second. The read-to-write ratio is enormous, often quoted north of 100:1, so almost every design decision here is about serving reads cheaply and keeping a giant cache tier warm and correct.
The News Feed problem is the canonical feed-design interview. A user opens the app and expects a personalized, ranked list of recent posts from friends, groups, and pages, assembled in a few hundred milliseconds. The naive approach, query every friend's posts at read time and sort, does not survive contact with a user who follows thousands of accounts. The classic answer is fanout: precompute each user's feed on write (push) so reads are cheap, or assemble it on read (pull) so writes are cheap. Pure push breaks the moment a celebrity with tens of millions of followers posts, because one write becomes tens of millions of feed inserts. Real systems use a hybrid: push for ordinary authors, pull for high-fanout accounts, merged at read time. On top of retrieval sits ranking, which at Meta moved from reverse-chronological to a multi-pass machine-learned model that scores candidates with neural networks. Underneath sits the hard part most candidates skip: the storage and cache tier, Facebook's TAO graph store over sharded MySQL fronted by memcache, where cache invalidation and read consistency are where systems actually fall over.
Asked at: Asked at Meta, and used as a feed-design proxy at Twitter/X, LinkedIn, Instagram, Pinterest, Amazon, and most companies that run a timeline or activity feed. It is one of the most common senior and staff system design prompts.
Why this question is asked
Interviewers like this problem because it forces a real decision under a real constraint rather than a checklist. The fanout question has no single right answer, so a strong candidate has to reason about the read-write ratio, follower distribution, and latency budget, then defend a hybrid. It also exercises the full stack at once: data modeling for a social graph, caching strategy and invalidation, ranking and candidate generation, pagination that stays stable while a user scrolls, and consistency choices like read-your-writes for your own posts. Weak candidates jump straight to push fanout and never mention the celebrity case; strong candidates surface it themselves and design around it.
Requirements
Always clarify these in the first 5 minutes of the interview. Do not start drawing boxes until both lists are agreed.
Functional requirements
- Show a user a personalized feed of recent posts from friends, followed pages, and joined groups.
- Support publishing a post (text, photo, video, link) and have it appear promptly in followers' feeds.
- Rank the feed by relevance, not just recency, using signals about the viewer and the content.
- Support infinite scroll with stable pagination so items do not duplicate or jump while scrolling.
- Let a user see their own post immediately after publishing (read-your-writes).
- Support likes, comments, and shares, and reflect fresh engagement counts in the feed.
- Mix in ads and recommended (unconnected) content alongside posts from connections.
- Handle media: photos and videos served through a CDN, not through the feed service.
Non-functional requirements
- Feed read latency in the low hundreds of milliseconds at p99, including ranking.
- Very high read availability; a stale or slightly degraded feed is better than an error.
- Eventual consistency is acceptable for others' posts; read-your-writes required for your own.
- Scale to billions of daily users and a read-to-write ratio well above 100:1.
- Absorb hot keys and celebrity posts without collapsing the write path.
- Protect the database from thundering herds when a hot cache entry expires or is invalidated.
- Durability for posts and the social graph; a published post must not be lost.
Back-of-envelope scale estimates
Show your math. Pulling numbers from thin air signals you have not thought about the load.
Daily active users
~2.1 billion
Company-reported Facebook DAU for 2024 was about 2.11 billion. Used as the base for read load.
Feed reads per day
~10 billion+ (Derived, estimate)
If ~2.1B DAU open the feed and refresh a few times a day, call it 5 sessions each, that is roughly 10B feed assemblies per day, about 120k per second average and several times that at peak. Order-of-magnitude estimate.
Candidates ranked per user per day
~1,000+
Meta has published that News Feed scores more than 1,000 posts per user per day on average, narrowed by a lightweight pass to roughly 500 before heavy scoring.
Posts created per day
hundreds of millions to low billions (estimate)
Not officially broken out. With billions of users and many authoring occasionally, writes land in the hundreds of millions to low billions per day, still tiny next to reads, which is why the ratio exceeds 100:1.
Social graph store throughput
~1 billion reads/sec, millions of writes/sec
Meta has described TAO as serving on the order of a billion reads per second and millions of writes per second across the fleet. This is the graph tier, not just feeds.
Feed storage per active user
~hundreds of entries cached (design choice)
A precomputed feed only needs the most recent few hundred post IDs per user, not full content. At ~600 IDs of ~8 bytes plus metadata, that is a few KB per user, so caching feed ID lists for active users is cheap. Derived design estimate.
High-level architecture
A write starts when a user publishes a post. The post is written to durable storage as a graph object, and an association edge is created linking the author to the post. A fanout service then decides how the post reaches feeds. For an ordinary author it pushes the post ID into the precomputed feed lists of that author's followers, which live in a fast store fronted by cache. For a high-fanout author, a celebrity or a large page, the system skips the push and marks the author as pull-based, because writing to tens of millions of feeds per post is wasteful and bursty. On the read path, a user opens the app and hits a feed aggregation service. That service reads the viewer's precomputed feed ID list (the push part), then pulls recent posts from the small set of celebrity or page accounts the viewer follows (the pull part), and merges the two into a single candidate set. Candidates are hydrated by fetching post content, author info, and engagement counts from the TAO graph tier, which is memcache in front of sharded MySQL. The merged candidates go through ranking: a lightweight model trims to a few hundred, then a heavier multi-task neural model scores each one, then a final pass applies diversity rules and injects ads. The ranked, hydrated, paginated result is returned. Media in each post is a URL served from the CDN, never streamed through the feed service itself.
In a real interview, sketch this on the whiteboard before diving into any single box.
Core components
Walk through each service. The interviewer wants to hear what each one owns, not just the names.
Post/Write service
Accepts new posts, writes the post object and its author edge durably, and enqueues a fanout job. It is the source of truth for content and returns fast so the author's own client can render the post immediately.
Fanout service
Decides push versus pull per author based on follower count and activity. For normal authors it inserts the post ID into followers' feed lists asynchronously through a queue. For celebrities and large pages it does nothing on write and relies on read-time pull, which is how the hybrid avoids the write explosion.
Feed store
Holds each active user's precomputed list of recent post IDs, typically an in-memory store like Redis or a memcache-backed structure. It stores IDs and light metadata, not full content, so it stays small and hot. Inactive users can have their lists evicted and rebuilt on demand.
Feed aggregation and ranking service
Reads the pushed feed list, pulls recent posts from followed high-fanout accounts, merges them, hydrates content, and runs the multi-pass ranking. This is the latency-critical read path and owns the per-request budget of a few hundred milliseconds.
TAO social graph store
Facebook's read-optimized graph cache over sharded MySQL, modeling everything as objects (users, posts) and associations (friendships, likes, authored-by). It absorbs the enormous read load with a cache tier and keeps MySQL as the durable backing store. Feed hydration and graph queries go through TAO.
Memcache tier
A massive look-aside cache holding hydrated objects, counts, and query results, organized in a leader/follower model per Facebook's memcache work. Front-end clusters read from follower caches; invalidations are propagated so stale data is deleted rather than updated.
Media and CDN pipeline
Photos and videos are uploaded, transcoded into multiple resolutions, stored in blob storage, and served from edge CDN nodes. The feed carries only URLs, so heavy bytes never pass through the feed service or the database.
Data model
Pick the right store per table. Justify each choice with the access pattern, not by reflex.
posts (object)post_idauthor_idcreated_atcontent_typebody_or_media_refvisibilityStored as a TAO object. body_or_media_ref points at text plus CDN URLs for media. Sharded by post_id; author_id lets you find an author's recent posts for the pull path.
edges (association)from_idtypeto_idcreated_atdataGeneric graph edge: friendship, follows, authored, liked, commented. Bidirectional friendships are two edges. Association lists are the primary read pattern TAO optimizes, so an author's followers and a viewer's follows are edge queries.
feed_listuser_idpost_idscore_or_tsauthor_idreasonPrecomputed per-user list of candidate post IDs from the push path, held in the feed store. Kept to a few hundred recent entries; older entries roll off. reason records whether it came from a friend, group, or page.
engagement_countspost_idlike_countcomment_countshare_countupdated_atHot counters kept in cache and periodically reconciled to durable storage. Counts are read on almost every feed render, so they are aggressively cached and updated with deltas rather than recomputed.
author_profileuser_idfollower_countis_high_fanoutverifiedregionDrives the push-versus-pull decision. is_high_fanout flips when follower_count crosses a threshold, moving that author to the pull path so their posts are not fanned out on write.
ranking_featuresviewer_idpost_idaffinitycontent_typerecencyembedding_refFeature vector assembled at read time for the ML ranker. affinity captures viewer-author relationship strength; embedding_ref points at learned representations. Computed per candidate, not stored long term.
Deep dives
These are the conversations the interviewer is steering you toward. Practice each one until you can talk through it without notes.
Fanout on write versus fanout on read, and why pure push breaks
Fanout on write precomputes each user's feed. When you post, the system inserts your post ID into the feed list of every follower, so a read is just fetching your own already-built list, which is fast and cheap. The cost is on the write: a post by someone with N followers is N inserts. That is fine for a user with 300 friends and catastrophic for a page with 40 million followers, where one post triggers 40 million writes and a burst that stalls the queue and delays everyone. Fanout on read does the opposite. Nothing happens on write; at read time you gather your follows' recent posts and merge them. Writes are trivial, but a read for someone following thousands of accounts becomes thousands of lookups plus a merge, which blows the latency budget. Neither pure model works at Facebook scale, which is exactly the point the interviewer wants you to reach on your own.
The hybrid and the celebrity/hot-user problem
The production answer is a hybrid keyed on follower count. Ordinary authors use push: their posts are fanned out to followers' feed lists on write, keeping reads cheap for the common case. High-fanout authors, celebrities and large pages, are flagged as pull-based, so their posts are not written into millions of feeds. At read time the aggregation service takes the viewer's pushed list and additionally pulls recent posts from the handful of high-fanout accounts that viewer follows, then merges. This bounds both sides: writes never explode because the few accounts with huge audiences skip fanout, and reads stay cheap because a viewer follows only a small number of those accounts, so the pull is a short list. The threshold is a tuning knob, and some designs push to active followers only while leaving dormant followers to rebuild on demand, which further trims wasted writes.
From reverse-chronological to multi-pass ML ranking
Early feeds were reverse-chronological, newest first. That is simple but shows you a loud acquaintance's twentieth post instead of your close friend's one important update, so Meta moved to machine-learned ranking. The published pipeline runs in passes to control cost. Inventory gathers eligible posts since your last visit plus resurfaced older ones. A lightweight pass 0 model cheaply trims the candidate set to roughly 500. Pass 1 does the heavy lifting: multi-task neural networks score each candidate in parallel across machines called predictors, predicting multiple outcomes such as probability of like, comment, or share, using features like content type, learned embeddings, and your past interactions. Those predictions are combined into a single value score. Pass 2 applies contextual rules such as content-type diversity so you do not see five videos in a row, and injects ads. The multi-pass shape exists because running the expensive model on every candidate for every user is too costly, so cheap filters run first and the expensive model runs on a few hundred survivors.
TAO: storing the social graph over sharded MySQL and cache
The feed is a view over a graph, so the storage question is really how to store and read a graph at scale. Facebook's answer is TAO, described in their USENIX ATC 2013 paper. TAO models the world as objects (a user, a post, a comment) and associations (friend, follows, authored, liked), with a small fixed set of queries such as fetch an object, fetch an association list, count associations. Underneath sit sharded MySQL databases for durability; in front sits a two-level cache tier that absorbs the read load, which Meta has described as around a billion reads per second. TAO is deliberately read-optimized and gives up strong consistency for availability and latency, offering eventual consistency with read-your-writes for the writer. This matters for feeds because hydrating a feed is thousands of small graph reads (who authored this, how many likes, is this author my friend) and TAO is the layer that makes those reads cheap and cacheable instead of hammering MySQL.
Caching at scale, invalidation, and thundering herds
The cache tier is where feed systems actually fall over, and Facebook's memcache work (NSDI 2013) is the reference. They run a look-aside cache and, on a write, delete the affected keys rather than updating them, because deletes are idempotent and safe to retry. A daemon called mcsqueal runs on the databases, watches the replication stream for committed changes, extracts the deletes, and broadcasts them to every front-end cache cluster in the region, which keeps caches across many machines coherent without the web tier coordinating it. They use a leader/follower cache structure and mechanisms like leases to fix two nasty problems: stale sets, where a slow write overwrites fresh data, and thundering herds, where a popular key expires and thousands of concurrent requests all miss and stampede the database at once. A lease lets one client refill the key while others briefly wait or serve slightly stale data. Any serious feed answer has to name cache invalidation and stampede protection, not just say add a cache.
Write path, feed aggregation, and stable pagination
When a user posts, the write service persists the post object and the authored edge, then hands off to fanout asynchronously so the author gets a fast response and their own client shows the post immediately. Followers' feed lists are updated out of band through a queue, so a brief delay before others see the post is acceptable. On read, aggregation merges the pushed list and the pulled celebrity posts, deduplicates, hydrates, and ranks. Pagination is subtle: if you paginate by a ranking score that is being recomputed, or by simple offset, posts shift between page fetches and users see duplicates or gaps as they scroll. The fix is to snapshot a stable ordering for the session, often a cursor over a materialized candidate list captured at first load, so page 2 continues exactly where page 1 ended even though the underlying feed keeps changing. New posts that arrive mid-scroll are surfaced via a refresh at the top rather than injected into the middle.
Consistency: read-your-writes for your own posts, eventual elsewhere
Feeds do not need strong consistency, and paying for it would wreck latency and availability. If a friend's post shows up two seconds late, nobody notices. But there is one case users are unforgiving about: your own action. Publish a post, or like something, and if a refresh does not show it, the app looks broken. So the requirement is read-your-writes for the author while everyone else gets eventual consistency. TAO and the memcache design both support this: the writer's region reads through to the master or sets a marker so subsequent reads by that user reflect the write, while other users read from caches and replicas that converge shortly after. In a multi-region setup, a common technique is a remote marker: after a write routed to the master region, the origin region marks the key so that user's reads go to the master until replication catches up and the marker is cleared. This gives the author a consistent view without forcing global synchronous replication.
Trade-offs to discuss
Every senior interviewer expects you to surface at least 3 of these. Pick the decisions, state the alternatives, and justify your choice.
Fanout on write versus fanout on read
Push makes reads cheap at the cost of write amplification; pull makes writes cheap at the cost of expensive reads. Given a read-to-write ratio above 100:1, you optimize for reads by default (push) and only pull for the accounts where push is ruinous.
Hybrid threshold versus a single uniform model
A uniform model is simpler to reason about but is wrong somewhere: pure push dies on celebrities, pure pull dies on high-follow readers. The hybrid adds a follower-count switch and merge logic, which is more moving parts but the only thing that holds at both extremes.
ML ranking versus reverse-chronological
Chronological is transparent, cheap, and easy to debug, and some users prefer it. ML ranking drives far more engagement and relevance but costs a multi-stage inference pipeline, heavy feature infrastructure, and a system that is hard to explain and audit. At Meta scale the engagement gains justify the cost.
Delete-on-write cache invalidation versus update-in-place
Updating the cache on every write keeps it warm but is not idempotent and races badly under concurrency and replication lag. Deleting the key is idempotent and safe to retry, at the cost of a subsequent cache miss and refill. Facebook chose delete for correctness.
Eventual consistency with read-your-writes versus strong consistency
Strong consistency across a global cache and replica tier would add latency and reduce availability for no user-visible benefit on a feed. Relaxing to eventual, while guaranteeing authors see their own writes, keeps the system fast and available where it matters.
Precompute and cache feed lists versus assemble everything on demand
Precomputed lists make the common read a single fast lookup but cost memory and background fanout work, and can waste effort on users who never log in. Building on demand saves storage but pushes cost onto the latency-critical read path. Precompute for active users, evict and rebuild for dormant ones.
How Meta News Feed actually does it
Facebook's real stack is well documented in its own papers and engineering posts. The social graph runs on TAO, described in the 2013 USENIX ATC paper by Bronson et al., which layers a read-optimized objects-and-associations cache over sharded MySQL and serves on the order of a billion reads per second. The cache tier is the subject of the 2013 NSDI paper Scaling Memcache at Facebook by Nishtala et al., which introduced the leader/follower structure, leases for stampede and stale-set protection, and the mcsqueal invalidation daemon that broadcasts deletes from the databases to regional cache clusters. News Feed ranking is covered in Meta's 2021 engineering post, which lays out the multi-pass pipeline: a lightweight pass to about 500 candidates, a heavy multi-task neural pass run in parallel on predictor machines scoring over 1,000 posts per user per day on average, and a contextual pass for diversity. The fanout hybrid itself, push for normal authors and pull for celebrities, is standard feed-design practice rather than a single named Meta paper, so treat the specific thresholds as general design rather than a published Facebook constant.
Lessons to study before this interview
If any of these topics are fuzzy, the interviewer will catch it. Each lesson is 15 to 60 minutes with diagrams, code, and a quiz.
Related system design interview questions
Practice these next. They lean on the same core building blocks as Meta News Feed.