Back to System design

Design Twitter / News Feed

hard
Scale: 5K tweets/s sustained, 60K/s peak; 10M timeline reads/s sustained, 100M/s peak Storage: ~500B/tweet × 500M/day = 250GB/day raw; timeline cache ~2.5 TB Twitter, Meta, LinkedIn
Case StudyFeedFanout

A social feed system serves a per-user, recent-first list of posts from accounts the user follows. Twitter / X is canonical; Facebook, Instagram, LinkedIn, TikTok share the architecture. Two forces dominate: writes are easy (a few tweets per user per day) but reads explode through follower fanout, and the feed must render in under 200 ms on every app open.

Scale5K tweets/s sustained, 60K/s peak; 10M timeline reads/s sustained, 100M/s peak
Storage~500B/tweet × 500M/day = 250GB/day raw; timeline cache ~2.5 TB

Key Concepts

1
1. The numbers. 300M MAU × 50% DAU × 2 tweets/day = 600M tweets/day ≈ 7K writes/s sustained, ~30-60K peak. Reads: 150M DAU × 10 sessions × 100 tweets = 150B reads/day ≈ 1.7M/s sustained, 17M/s peak. Read:write ratio ~250:1 — this is why fanout-on-write looks attractive.
1. The numbers.
2
2. Push vs pull vs hybrid. Push (fanout-on-write): when a user posts, a worker appends the tweet to each follower's timeline cache. Read = one Redis call. Breaks for celebrities — one tweet becomes millions of writes. Pull (fanout-on-read): at read time, fetch the follow list, pull recent tweets from each, merge. Cheap writes, expensive reads — bad UX. Hybrid (production default): push for normal accounts; for celebrities (followers > 1M), skip fanout and have readers pull from the celebrity's outbox at read time, merge with their precomputed timeline.
2. Push vs pull vs hybrid.
3
3. Ranking is now mandatory. Pure chronological is what users say they want and not what they actually engage with. Pipeline: candidate generation (precomputed timeline + trending + recommendations) → feature fetch (online feature store) → ML scoring (GBDT or DNN) → rerank for diversity/freshness/business rules → log impressions for next training cycle.
3. Ranking is now mandatory.
4
4. Storage. Tweet store (Cassandra wide row by tweet_id) for durable text + meta. Timeline cache (Redis sorted set per user, capped at ~800 entries) for hot reads. Cold pagination falls back to durable store. Search via async indexer → Elasticsearch. Media on S3 + CDN. Notifications on a separate path.
4. Storage.
5
5. Production references. Twitter Timeline + Manhattan (KV); Redis for in-memory timelines. Instagram: Cassandra timelines + Redis cache, ranked feed. Facebook: TAO graph + dense ranking. TikTok For-You: heavy ML reranking, less fanout-driven (recommendation-first). LinkedIn Volur.
5. Production references.

High-level design

Write path: client → API → tweet service (write to durable store) → Kafka FanoutEvent → fanout workers → timeline cache.
Read path: client → API → timeline cache (precomputed) + celebrity outbox pulls (merged) → ranker → response.
Search: tweets → Kafka → Elasticsearch indexer.
Media: tweets with photos/videos → S3 + CDN.
Async pipelines: notifications, analytics, recommendation training.

Components

  • Tweet service (write path; sharded by tweet_id).
  • Social graph service (followers, following).
  • Fanout workers (Kafka consumers).
  • Timeline cache (Redis sorted set per user, capped at 800 entries).
  • Durable timeline store (Cassandra wide row) for cold/pagination.
  • Ranker (TF Serving / Triton).
  • Search indexer + Elasticsearch.
  • Media service (S3 + CDN, transcoding pipeline).
  • Notification service.
  • Anti-abuse service (spam, hate, NSFW).

Fanout strategies in depth

Push (fanout-on-write): one write becomes N timeline appends. Read latency: one Redis call. Write cost: O(followers). Bad for celebrities.

Pull (fanout-on-read): no fanout at write. Read fetches follow list, pulls recent tweets from each, merges. Write cheap; read O(following) — bad UX at scale.

Hybrid: push for follower count < threshold (e.g., 1M); pull for celebrities. Read = precomputed + small set of pulls.

Pull cap: only pull from top-K celebrities the user follows to bound read cost.

Active-user push: only fan out to active users (logged in recently); inactive users get pull at next login. Cuts fanout cost dramatically.

Ranking pipeline

Candidate generation: pull from precomputed timeline + celebrity outboxes + topical sources (hashtag follows, recommendations).

Feature fetch: online feature store (Redis/Feast) with last-minute features (recency, recent engagement).

Model scoring: GBDT for cost-efficiency or DNN for richer features.

Re-rank: diversity rules (no two consecutive items from same source), freshness boost, business rules (ads).

Logging: impressions + engagement signals → Kafka → training data lake.

Trade-offs

Push: fast reads, expensive writes for high-follower users.

Pull: cheap writes, slow reads.

Hybrid: best of both, more complex.

Chronological vs ranked: chronological is simpler and what users say they want; ranked actually drives engagement.

Timeline cache cap: 800 entries works for the open-feed use case; pagination falls back to durable store.

Strong consistency on social graph: hard. Most systems are eventually consistent for follows — accept that a new follow takes seconds to show in the feed.

Real-world references

  • Twitter: 'Timeline' system uses hybrid push/pull; Manhattan (KV) for tweets; Redis for timelines.
  • Instagram: Cassandra timelines + Redis cache, ranked feed.
  • Facebook: TAO (graph) + dense ranking infrastructure.
  • TikTok: For-You page is candidate generation + heavy ML reranking, less fanout-driven.
  • LinkedIn: feed system Volur, GraphQL gateway.