The system design question
Design the news feed. People see recent posts from friends and pages they follow, ranked so the most interesting are near the top, and the feed should load quickly.
Agree on the scope (5 minutes)
Say up front what you're covering.
| We'll design | We'll skip |
|---|---|
| Publishing a post | Ads in the feed |
| Getting it into followers' feeds | Comments and likes themselves |
| Ranking the feed | Uploading photos and video |
| Loading the first screen quickly | Privacy rules beyond 'run the check' |
Then agree on what "good" means:
- Fast: the first screen of the feed loads in about 200 ms on the server side.
- Fresh enough: a friend's post shows up within a few seconds to a minute.
- Relevant: the most interesting posts are near the top, even when they aren't the newest.
- Handles celebrities: someone with 100 million followers posting doesn't knock anything over.
Rough numbers (5 minutes)
Assumptions, not real figures: 2 billion people a day, 10 feed loads each, 1 billion new posts a day, about 300 friends and pages each, and a few accounts with 100 million followers. Meta's design round is often 45 minutes, so get through this in a couple of minutes.
- ~230K
- feed loads a second
- ~12K
- new posts a second
- ~3.5M
- feed inserts a second if we push everything
- ~16 TB
- of feed lists in cache
| Question | Rough math | What it means |
|---|---|---|
| How many feed loads? | 2 billion × 10 ÷ 86,400 | About 230K a second, around 700K at peaks |
| How many posts? | 1 billion ÷ 86,400 | About 12K a second |
| What if every post is pushed to every follower? | 12K × 300 followers | About 3.5 million writes a second. Big, but doable for normal accounts |
| And one celebrity post? | 1 post × 100 million followers | 100 million writes for one post. Pushing that doesn't work |
| How much to keep a feed per person? | 2 billion × 500 post IDs × 16 bytes | About 16 TB. Fits in a big cache cluster |
The overall design (10 minutes)
- A new post is saved once in the post store, and an event goes onto a queue.
- Fan-out workers look up the poster's followers and add the post ID to each follower's feed list in a cache. Accounts with huge followings are skipped.
- When someone opens the app, the feed service reads their feed list, pulls recent posts from the few huge accounts they follow, and merges them.
- It runs the privacy check, scores the candidates, and returns the top 20 or so.
- The app fetches post details, photos and counts in one batch, with media coming from a CDN.
What the apps need to do
| Action | Who does it | What's sent |
|---|---|---|
| Publish a post | The poster | Content, media IDs and the audience |
| Get my feed | The app | A cursor for where you left off, and how many posts |
| Mark posts as seen | The app, in the background | Post IDs that were on screen |
| Follow or unfollow | Anyone | The account to follow |
What we store and where
| Data | Where it goes | Why |
|---|---|---|
| Posts | Post store, split by post ID, with a cache in front | Written once, read many times |
| Who follows whom | Graph database, split by user | Fan-out needs followers, feed loading needs followees |
| Feed lists | Cache cluster, split by user | The latest few hundred post IDs per person, ready to read |
| Seen posts | Key-value store, kept a few days | So the same posts don't keep coming back to the top |
| Engagement signals | Event stream into a features store | Inputs for ranking, like how often you interact with someone |
Step 1: Push, pull, or both (12 minutes)
Push (fan-out on write) means copying each new post ID into every follower's feed list as soon as it's posted. Reading is then one lookup. Pull (fan-out on read) means building the feed when someone opens the app by fetching recent posts from everyone they follow. Writing is cheap, but reading means 300 lookups and a merge on every load.
With 230K reads a second, pull everywhere is too slow. With celebrities, push everywhere is too expensive. So mix them: push for normal accounts, pull for accounts above some follower count, say 10,000. Each viewer follows only a handful of huge accounts, so pulling those at read time is a few extra lookups.
The fan-out runs through a message queue, so posting returns right away and the work happens in the background. Workers handle followers in chunks and can be added when the queue grows.
Don't push to people who aren't there
A lot of followers haven't opened the app in weeks. Skip pushing to anyone inactive for, say, 30 days. If they come back, build their feed with a pull the first time, then they're back on push.
Step 2: Ranking (10 minutes)
Ranking happens in stages, because scoring with a heavy model is too slow for thousands of posts. First, gather candidates: the latest few hundred from the feed list plus the pulled celebrity posts. Drop anything the viewer can't see or has already seen.
Then score each one. A simple version is a weighted sum of a few signals: how often you interact with the author, how old the post is, how much engagement it's getting, and what kind of post it is. A real system would use a model that predicts the chance you'll like, comment or share, but you don't need to design the model in this round.
Sort by score, and use a small heap if you only need the top 20. Then apply a few rules on top, like not showing three posts from the same person in a row.
- Keep the ranked list for that session in a cache, so scrolling down reads the next page from it without ranking again.
- Fresh posts arriving mid-session go into a 'new posts' banner rather than reshuffling what the person is looking at.
Step 3: Loading fast (8 minutes)
Feed lists, post objects and counts like likes all live in caches. The feed service fetches the 20 posts it needs in one batched call, not 20 separate ones. Like counts can be a little behind, which nobody notices.
Use a cursor for paging, the ID and score of the last post shown, so new posts don't make you see duplicates as you scroll. Return about 20 posts and let the app fetch the next page before the person reaches the bottom.
Everything is split by user ID, so one person's feed is one cache lookup on one machine. Photos and videos come from a CDN, so the feed response itself stays small.
Choices you should be able to defend
| We chose | Instead of | Because | We'd reconsider if |
|---|---|---|---|
| Push for most accounts, pull for huge ones | Pure push or pure pull | Fast reads without 100 million writes for one post | Almost nobody had huge followings, so pure push was simpler |
| Fan-out through a queue | Writing to followers' feeds while posting | Posting stays fast, and fan-out can lag a bit under load | We needed posts to appear everywhere instantly |
| Ranking at read time | Ranking when posts are pushed | Scores depend on the viewer and change as engagement comes in | Ranking cost got too high, so we'd precompute a rough score |
| Only keeping a few hundred IDs per feed | Keeping everyone's whole history | Nobody scrolls that far, and memory is expensive | People often scrolled back days, so we'd page older posts from the database |
What could go wrong (5 minutes)
| What happens | What we do about it |
|---|---|
| Fan-out workers fall behind | Posts show up in feeds late, but nothing's lost. Add workers. The poster's own feed reads their post straight away |
| A feed cache node dies | Rebuild those feeds with a pull on the next load. It's slower once, then cached again |
| A celebrity posts and millions refresh at once | Their post is pulled from a cache, so it's one hot key with lots of copies, not millions of database reads |
| The ranking service is slow | Fall back to newest first. A plain feed beats a blank screen |
| Someone deletes a post | Remove it from the post store. Feeds still hold the ID, but it's dropped when the post can't be loaded |
Follow-up questions (5 minutes)
How would you add ads?
Treat ads as another candidate source that gets merged in at fixed spots, with its own ranking and its own limits on how often ads show.
What if someone unfollows a person?
Stop new fan-out to them, and filter that author out at read time. Old IDs in the feed list fade out on their own.
How do you stop the same viral post showing up again and again?
The seen-posts store drops anything the person has already scrolled past, and the ranking rules limit repeats from the same source.
How the 60 minutes add up
| Minutes | What you're doing |
|---|---|
| 0–5 | Agree on what you're building |
| 5–10 | Rough numbers |
| 10–20 | Draw the overall design |
| 20–32 | Push, pull, or both |
| 32–42 | Ranking |
| 42–50 | Loading fast |
| 50–55 | What could go wrong |
| 55–60 | Follow-up questions |
Key concepts used here
- Message queues and event streamsKeep services from depending on each other, and handle traffic spikes.
- Caching strategiesMake reads faster, and figure out what to do when data changes.
- Sharding and consistent hashingSplit data across machines and keep it balanced.
- Heaps and priority queuesAlways have the smallest or largest item ready.
- Blob storage and CDNsStore big files cheaply and serve them from close to your users.
Further reading
We wrote this sample answer ourselves.
Practice Loop is independent and isn't affiliated with or endorsed by Meta.