Design a News Feed
The home timeline of Twitter, Instagram or Facebook: posts from people you follow, ranked, fresh, and fast for hundreds of millions of users.
Difficulty: hard. Patterns: fan-out, ranking, caching, social. Reported at Meta, X, LinkedIn, Pinterest, Snap, TikTok.
Study shows every answer; Practice hides them until you have produced your own.
Functional requirements
- Create a post. Text, images, video. Visibility: public or followers-only.
- Follow and unfollow users. Asymmetric follow graph. Some accounts have 100 M followers.
- View the home feed. Posts from followed accounts, newest first or ranked. Infinite scroll with stable pagination.
- View a user's profile timeline. That user's own posts, newest first.
- Like, comment, share. Counters shown on every post; engagement feeds ranking.
- Feed freshness. A new post from someone you follow appears within seconds on refresh.
- Out of scope. Search, DMs, notifications, ads insertion (mention where it would plug in), content moderation pipeline.
Non-functional requirements
- Scale (500 M DAU). Reads dominate: each user opens the feed several times a day; most never post.
- Feed load latency (p99 < 300 ms). First page of the feed must be a cache read, never a query over the follow graph.
- Post visibility delay (< 5 s for most, < 60 s for celebrity posts). Eventual consistency is fine; users tolerate a short delay but not missing posts.
- Availability (99.99 % reads). Writes can degrade (post queued) as long as reading the feed works.
- No missing or duplicate posts. Pagination must be stable while new posts arrive.
- Privacy. Followers-only posts never leak to non-followers, including through caches after an unfollow or block.
- Cost. Fan-out is the dominant cost. The design must bound work per post regardless of follower count.
Back-of-envelope estimates
- Posts per second: ~6 k avg · 30 k peak. 500 M DAU, ~1 % post daily, ~1 post each = 5 M/day, plus reshares ≈ ~6 k/s. Peaks around events 5×. Writes are cheap; what they trigger is not.
- Feed reads per second: ~60 k avg · 300 k peak. 500 M DAU × 10 feed opens/day = 5 B/day ≈ 58 k/s, peak 5×. Each open reads one page (20–50 posts). Every one must be a cache hit.
- Average followers per user: ~200 (median ~50). Heavy-tailed. Mean around 200, median under 100, and a few thousand accounts with over 1 M followers. The mean sizes total fan-out; the tail breaks naive designs.
- Fan-out writes per second: ~1.2 M. 6 k posts/s × 200 followers = 1.2 M feed inserts/s average, if every post fans out to every follower. One celebrity post with 100 M followers is 100 M writes on its own, which is why celebrities are handled differently.
- Feed cache size: ~2–5 TB (ids only). Cache the most recent 500 post ids per user (8 B each ≈ 4 KB with metadata): 500 M × 4 KB = 2 TB for active users. Materialised hydrated posts are separate. Realistically 2–5 TB of Redis for feed lists; the 400 TB figure is what you would need if you cached full post bodies per user, which is why you do not.
- Post storage growth: ~2 PB/year (media excluded). 5 M posts/day × ~1 KB metadata × 365 ≈ 1.8 TB/yr of rows; media is ~2 MB average × 40 % of posts ≈ 1.5 PB/yr in object storage. Media dominates storage; metadata dominates query load.
- Ranking inference per second: ~15 M candidates. 300 k feed opens/s at peak × ~50 candidates scored each = 15 M scores/s. Per-candidate inference must be sub-millisecond, batched, and cached per (user, session).
Components
- Client: Web and mobile apps. Renders the feed, prefetches the next page, dedupes on post id, and records impressions and engagement for ranking.
- API gateway: Auth, rate limiting, request routing. Stateless.
- Post service: Creates posts, uploads media via pre-signed URLs, writes the post row, and publishes a post-created event. Owns the profile timeline read path.
- Feed service (read path): Serves the home feed: reads the user's precomputed feed list, merges in celebrity posts fetched at read time, hydrates post bodies, calls ranking, and returns a page with a stable cursor.
- Fan-out workers: Consume post-created events, look up followers, and push the post id into each follower's feed list. Skip fan-out for celebrity authors and inactive followers. Horizontally scaled; the biggest compute pool in the system.
- Ranking service (ML inference): Scores candidate posts for a user with a model over user, author, post, and engagement features. Returns an ordering plus diversity rules (no three posts from one author in a row).
- Social graph service: Follows, followers, blocks, mutes. Answers "followers of X" (for fan-out) and "does A follow B" (for privacy checks) from a cache in front of a sharded store.
- Event bus (Kafka): post.created, post.deleted, engagement events, follow/unfollow. Fan-out workers, counters, and ranking feature pipelines consume from here.
- Feed cache (Redis · list per user): For each active user, a sorted list of the most recent ~500 post ids from non-celebrity followees, keyed by user id. The entire first page of the feed is one ZREVRANGE. Evicted for users inactive for weeks and rebuilt on demand.
- Post cache (Redis · post id → body): Hydrated post bodies and counters by post id. Hit rate is very high because recent posts are read by all their followers within hours. Backed by the posts DB.
- Posts DB (Cassandra / sharded MySQL): Post rows keyed by post id (time-ordered), plus a per-author timeline table keyed by (author id, time) for profile pages and celebrity pulls. Append heavy.
- Graph DB (sharded by user id): Follower and following adjacency lists, both directions materialised, sharded by user id so "followers of X" is one shard read. Celebrity follower lists are chunked.
- Media storage + CDN: Images and video uploaded directly from the client with pre-signed URLs, transcoded asynchronously, served via CDN. Posts reference media by id.
- Counter service (likes · comments · views): Aggregates engagement events into per-post counters with approximate, eventually consistent values. Writes to the post cache; persists periodically.
User flows
- Create a post and fan it out. The write path. The post is durable in milliseconds; delivery to followers' feeds happens asynchronously and is bounded regardless of follower count.
- Load the home feed. The read path. One cache read for the precomputed list, one small query for celebrity posts, hydrate, rank, paginate. No follow-graph traversal on the hot path.
- A celebrity with 100 M followers posts. The case that breaks fan-out on write. Here the post costs nothing to publish and is pulled by readers, which spreads the cost over time and cache hits.
- Scroll: stable pagination while new posts arrive. Offset pagination breaks the moment a new post lands. Cursors anchored on time-ordered ids keep the scroll stable and duplicate-free.
- Unfollow, block, and privacy. Precomputed feeds are copies. Every copy must respect the current follow graph and visibility, which means invalidation and read-time checks.
Deep dives
- Fan-out on write vs fan-out on read. Do you build each user's feed when a post is created, or when the user opens the app?
- Ranking the feed. Reverse chronological is simple and honest. Why rank, and how do you do it without making the feed slow?
- Feed cache design. What exactly is stored per user, where, how big, and what happens when it is lost?
- Hot keys and celebrity read storms. One post read by ten million people in five minutes. What melts first?
- Consistency and freshness guarantees. What can a user actually rely on? Which delays and anomalies are acceptable, and which are bugs?