Skip to main content
Hard TimelineFanoutShardingCachingSearch

Design Twitter — Social Network and Microblogging

Design Twitter: tweet posting, following, home timeline, trending topics, and search. Covers fanout-on-write vs read strategies, timeline caching, and sharding at 200M daily active users.

22 min read · Similar: Mastodon, Threads, Bluesky

Requirements and Scale

Functional: post tweets (280 chars), follow users, home timeline (tweets from followees, reverse-chronological), user timeline (user's own tweets), retweets, likes, trending topics, search. Non-functional: high availability, eventual consistency for timeline is acceptable, low latency (< 200ms).

Scale: 1B accounts, 200M daily active users, 500M tweets/day ≈ 6,000 tweets/sec. Timeline reads: 300K requests/sec. Average user follows 200 people.

Timeline Generation — The Core Challenge

Home timeline for User A = reverse-chronological union of tweets from all people A follows. Naive approach: on each read, fetch all followees, query their tweet shards, merge-sort. Too slow at scale.

Fanout-on-write (push model): when a tweet is posted, immediately push the tweet_id into each follower's home_timeline cache (Redis sorted set, score = timestamp). Fast reads — timeline is pre-built. Problem: celebrities with millions of followers create massive write storms (Lady Gaga posting = 60M writes). Twitter uses a hybrid: push for regular users, pull (merge at read time) for celebrities.

graph TD
  Tweet["User posts tweet"] --> FanoutWorker["Fanout Worker"]
  FanoutWorker --> FollowerList["Follower List Service"]
  FanoutWorker --> TimelineCache["Redis Timeline Cache
(per-user sorted set)"]
  TimelineRead["Timeline Read API"] --> TimelineCache
  TimelineRead --> CelebrityTweets["Celebrity Tweets DB
(pulled at read time)"]

Data Storage

Tweet table: tweet_id (Snowflake ID), user_id, content (280 chars), created_at, retweet_of, like_count. Sharded by tweet_id. User table sharded by user_id. Social graph (follows): UserFollow table in a graph-optimized store or MySQL sharded by follower_id to efficiently answer "who does user X follow?"

Media (images, videos): stored in S3, CDN-served. Tweet DB stores CDN URLs. Tweet Snowflake ID encodes timestamp in high bits → tweets are naturally sortable by creation time without sorting in DB.

Trending Topics

Count hashtag/phrase mentions in the last N hours using a sliding window counter. Architecture: ingest tweet stream into Kafka → Storm/Flink streaming job counts mentions per window → top-K results stored in Redis → trending API reads from Redis. Windowed counting with weighted recency: more recent mentions count more. Trend lists are per-region and per-language.

Search

Tweets need full-text search. Solution: Elasticsearch cluster. Tweets are indexed as they are created: tweet_id, user_id, content (tokenized), timestamp, geo. Search query hits Elasticsearch, returns matching tweet_ids sorted by relevance + recency. Then fetch tweet content from cache/DB. For real-time trending search, an in-memory sorted set (Redis) tracks hot search terms.

Replication and Reliability

Each shard: 1 primary + 2 replicas across availability zones. All writes go to primary and synchronously replicate to replicas before acknowledging to the app. Timeline caches in Redis use Redis Cluster with AOF persistence. Critical user data (tweets, follows) is never lost — durability over consistency. Application tier is stateless, deployed across multiple AZs.

View all →

Syed Peera Saheb

LinkedIn · Substack

Buy me a coffee