Skip to main content

Design Twitter for Millions of Users

A microblogging platform at Twitter/X scale — tweet ingestion, hybrid fan-out timelines, typeahead search, and real-time notifications, each broken into its own diagram.

synchronous: caller waits
asynchronous: fire & forget

Denser dots = higher throughput. Hover any edge for its full contract.

//The Contract

Requirements

Functionalwhat the system must do
  • Users can post tweets (with optional images, video, or GIFs), and each tweet appears in followers' timelines within seconds.
  • Users can follow/unfollow accounts and view a home timeline aggregating tweets from everyone they follow.
  • Users get instant, ranked suggestions as they type in the search box, and can run full-text search over tweets and accounts.
  • Users receive near-real-time notifications for likes, retweets, replies, and mentions, even when the app is closed.
  • The system surfaces trending topics and hashtags computed from recent tweet volume.
Non-functionalhow well it must do it
  • Massive scale — hundreds of millions of daily active users and a firehose of hundreds of millions of tweets per day.
  • Low latency — the home timeline and search suggestions must both return in well under a second.
  • High availability — the posting and timeline paths must survive individual node or shard failures with no single point of failure.
  • Eventual consistency is acceptable almost everywhere (timelines, counts, trends) in exchange for availability and throughput.
  • Extreme fan-out — a single tweet from a top account must reach tens of millions of followers within seconds.
//Back of the Envelope

Scale Estimates

Rough, order-of-magnitude numbers. The point is to justify the architecture, not to be exact.

Daily Active Users
300M
generates billions of timeline reads per day
Tweets / Day
500M
~6,000 writes/sec sustained, far higher during major events
Timeline Read:Write
~1000:1
reads dominate — push cost onto the cached read path
Peak Suggest QPS
500K/s
keystroke traffic on the search box dwarfs tweet volume
Suggestion Trie Size
~12 GB
small enough to fully shard and replicate in memory
Celebrity Fan-out
50M+
one tweet can mean 50M+ timeline writes if pushed naively
//Why It Looks Like This

System Evolution

No system is born with queues and caches. Every box was added because something was about to break. Play a stage and the diagram above shrinks to what existed at that point in the story.

01

The MVP — tweet ingestion only

The simplest version of the system: a client submits a tweet through an API gateway to a Tweet Service, which mints a globally unique ID via a Snowflake-style generator, persists the tweet in Cassandra, and issues pre-signed URLs so media uploads bypass the API tier entirely.

There are no timelines, no search, no notifications — just the core write path. Every tweet is written synchronously, and users read by scanning the database directly. This works for a few thousand users but collapses under millions.

02

Add precomputed timelines — fan-out-on-write

Scale pressure: With millions of users, scanning every tweet to find those from followed accounts is thousands of times too slow — we need precomputed feeds

A Kafka event bus decouples the write path from the read path. After persisting a tweet, the Tweet Service publishes a tweet_created event. A Fan-out Dispatcher reads the author's follower count from the Social Graph Store and decides between push (most users) and pull (celebrities with 50M+ followers).

The Fan-out Worker continuously drains the stream and pushes tweet IDs onto every follower's precomputed timeline in both the durable Cassandra store and the Redis cache. The Timeline Service now assembles feeds by reading precomputed ID lists from Redis, hydrating full tweet content from the Tweet Store, and merging in celebrity tweets from a dedicated pull cache — all in well under a second.

03

Add notifications and trending topics

Scale pressure: With engagement growing, users need real-time alerts when their content is liked or mentioned, and the platform must surface what is trending right now

Engagement events — likes, retweets, replies, mentions — flow through a shared Kafka topic decoupled from the action that caused them. A Notification Worker consumes each event, builds a per-recipient payload, appends it to a DynamoDB Notification Store sharded by user ID, and forwards eligible events to the Push Gateway (APNs/FCM) for immediate mobile delivery.

Independently, the Trending Aggregator maintains a sliding-window count of hashtag and topic mentions from the same engagement stream, refreshing a Redis cache with the top-N topics per region. The Notification & Trends Service serves both feeds as a read-only API — it never computes anything itself.

04

Add typeahead search and full-text search

Scale pressure: At hundreds of millions of users, users expect instant, ranked suggestions with every keystroke and full-text search across tweets and accounts — browsing timelines is no longer enough

A Typeahead Service serves prefix suggestions by checking Redis first (hot prefix cache), then falling back to a sharded cluster of in-memory ranked tries where every node stores its top-K completions pre-sorted by popularity — a keystroke is a lookup, not a computation.

Offline, a Query Log in Kafka feeds an Aggregation Job that tallies query frequencies. The Trie Builder periodically reads fresh frequencies and atomically swaps a newly built trie onto the serving shards, so the hot read path never pays a rebuild cost. Separately, the Search Service handles full-text queries over the Elasticsearch index for submitted searches — a heavier path than typeahead's per-keystroke lookups.

This is the finished architecture: four semi-independent sub-systems — write path, timeline, notifications, search — each decoupled by Kafka, each scaling on its own signal.

//Follow the Data

Request Flows

A diagram shows what exists; a trace shows what happens. Press play on a flow, or click any step, and the diagram above lights up the exact path that request takes.

Flow 01

Post a tweet

The write path — from compose to a durable, event-published tweet. Scoped entirely to frame 1.

Flow 02

Load the home timeline

The read path — how a user's feed is assembled with sub-second latency. Scoped entirely to frame 2.

Flow 03

Type-ahead search suggestions

How a keystroke becomes an instant, ranked suggestion. Scoped entirely to frame 3.

Flow 04

Rebuild the suggestion trie offline

The offline pipeline that keeps typeahead rankings fresh without ever blocking a live query. Scoped entirely to frame 3.

Flow 05

Deliver a notification

From an engagement action to a push notification and a readable feed. Scoped entirely to frame 4.

//Component Breakdown

Key Components

Every box on the canvas, and the job it does. Click a card to locate it in the diagram; click the node itself for the full deep dive.

client×4
network×4
compute×13
database×8
cache×4
queue×3
storage×1
external×1
//Deep Dive

Architecture Breakdown

1. Tweet Ingestion & Write Path

Handles the moment a tweet is created: validating content, minting a globally unique ID, persisting the tweet, and kicking off everything that has to happen next.

  • A dedicated ID Generation Service mints Snowflake-style IDs so tweet IDs are unique and roughly time-sortable without a single central counter
  • Media uploads bypass the API tier entirely via pre-signed URLs straight to object storage
  • Every write ends with a single Kafka event — the write path never blocks on fan-out, search indexing, or notifications

2. Home Timeline Generation (Read Path)

Serves the personalized feed a user sees on open, in well under a second.

  • A Fan-out Worker continuously drains the tweet-created stream and pushes new tweet IDs onto every follower's precomputed timeline — the classic fan-out-on-write
  • Accounts with tens of millions of followers are exempted from push fan-out; their tweets are merged in at read time from a dedicated cache instead
  • Redis holds the hot, precomputed timeline; Cassandra is the durable system of record behind it

3. Typeahead Search & Full-Text Search

Turns every keystroke in the search box into an instant, ranked suggestion, and serves full-text search over tweets and accounts.

  • Suggestions are never ranked on the fly — a sharded, in-memory trie stores each prefix's top-K completions pre-sorted, so a keystroke is a lookup, not a computation
  • An offline pipeline aggregates query and click frequency from a log of every search, then periodically rebuilds the trie and atomically swaps it onto the serving shards
  • A Redis cache absorbs repeat lookups for hot prefixes before they ever reach a trie shard

4. Notifications & Trending Topics

Fans engagement events (likes, retweets, replies, mentions) out to the people who need to see them, and surfaces what's trending right now.

  • Engagement events flow through a shared Kafka topic, decoupling the action that caused a notification from however many notifications it produces
  • A Notification Worker writes to a per-user notification feed and forwards eligible events to a push gateway for delivery even when the app is closed
  • A separate Trending Aggregator keeps a sliding-window count of hashtag/topic volume in Redis, refreshed independently of the notification path
//Trade-offs

Design Decisions

An architecture is a record of trade-offs. For every major choice here: what won, what lost, and why the constraints made it so.

01

Tweet ID generation

ChoseSnowflake-style distributed ID generator
OverPer-shard database auto-increment

At ~6,000 writes/sec sustained (and much higher during spikes), a single auto-increment counter becomes a contention point, and per-shard counters can collide across shards. A Snowflake-style generator produces IDs from a timestamp, worker ID, and sequence number, giving global uniqueness and rough time-ordering with zero coordination between nodes.

02

Timeline: hybrid fan-out

ChosePush (fan-out-on-write) for most users, pull (fan-out-on-read) for celebrities
OverFan-out-on-write for everyoneFan-out-on-read for everyone

An account with 50M+ followers would require 50M+ timeline writes per tweet under pure push — the estimates make that write explosion untenable. Pure pull would make every timeline read for every user pay a fan-in join, which is too slow at ~1000:1 read-to-write ratio. The hybrid splits the difference: most users get a precomputed, instant feed, while the rare high-follower accounts are merged in at read time.

03

Search: precompute rankings, don't compute them per query

ChoseTrie with top-K suggestions cached at every node
OverRank candidates live from a query-time index

At a peak of 500K suggest requests/sec, ranking candidates on every keystroke is not viable. Precomputing each prefix's top-K completions ahead of time turns every request into a lookup instead of a computation — the core insight behind both referenced typeahead designs.

04

Search: offline rebuild cadence

ChoseBatch rebuild (minutes to hours) with atomic swap, plus a lightweight real-time overlay
OverUpdate the trie in place on every query

In-place updates to a structure being read 500K times a second would require locking that the hot path can't afford. Rebuilding fresh and swapping atomically keeps every live read lock-free; a small real-time overlay covers the gap for suddenly trending terms without paying for a full rebuild.

05

Notification storage

ChosePer-user notification feed in DynamoDB
OverRelational table joined at read time

Notification reads are always single-item lookups by user ID — exactly DynamoDB's partition-key access pattern. This gives predictable latency even during a viral-tweet spike that floods the write path with mentions and likes for one popular thread.

06

Social graph storage

ChoseDedicated adjacency store, separate from tweet content
OverFollower lists as rows in the same store as tweets

Follower lookups sit on the hot path for every fan-out decision and every timeline push, at a completely different volume and access pattern than tweet writes. Isolating the graph store lets it be sharded and scaled by adjacency-lookup load rather than being coupled to tweet throughput.

//What Breaks First

Bottlenecks & Failure Modes

Reading a system means sensing where it cracks under 10× load. These are the pressure points of this design, and how it holds.

Risk 01

Timeline: celebrity write explosion

Failure mode

A tweet from an account with 50M+ followers would need 50M+ timeline writes within seconds if fanned out naively, overwhelming the Timeline Store and the Fan-out Worker.

Mitigation

The Fan-out Dispatcher routes celebrity tweets away from push fan-out entirely. Their tweets are fetched on demand from the Celebrity Tweet Cache and merged into each requester's timeline at read time instead.

Risk 02

Search: hot prefix skew

Failure mode

A small number of popular prefixes receive a hugely disproportionate share of the 500K/s suggest traffic, which can overload whichever single trie shard happens to own them.

Mitigation

Skew-aware prefix sharding splits busy prefixes across more shards than rare ones, and the Suggestion Cache absorbs a large fraction of repeat hits before they ever reach a shard.

Risk 03

Search: trending term lag

Failure mode

With only a periodic offline rebuild (minutes to hours), a breaking-news term can spike in seconds and stay invisible in suggestions until the next rebuild cycle.

Mitigation

A lightweight real-time overlay is blended into typeahead results at query time, and the separate Trending Aggregator keeps its own short sliding window in Redis independent of the trie rebuild cadence.

Risk 04

Notifications: viral tweet thundering herd

Failure mode

A single viral tweet can generate millions of mention, like, and reply events within minutes, all needing to fan out through the Notification Worker and Push Gateway simultaneously.

Mitigation

Kafka buffers the engagement event burst so the Notification Worker drains it at a sustainable rate rather than being hit synchronously, and notification writes are batched per recipient shard.

Risk 05

Timeline: cold-follower cache stampede

Failure mode

A user who hasn't opened the app in a while has no warm entry in the Timeline Cache; if many dormant users return around the same event, that's a burst of cold reads hitting the Timeline Store at once.

Mitigation

The durable Timeline Store in Cassandra is sized for this fallback path, and cache repopulation happens lazily on read rather than requiring a full timeline recomputation.

//Break Things on Purpose

Failure Lab

Most of this architecture exists because any one box can die. Take a component offline and the diagram above shows the blast radius: what goes down, what degrades, and what the user feels.

Tweet Service

REST API

Tweeting fails — users cannot post new content. But timelines, search, and notifications keep working from cached data.

Tweet Store (Cassandra)

Cassandra

New tweets cannot be persisted — tweeting fails. Existing tweets remain readable from the cache and CDN. Timeline hydration for old tweets is lost.

Tweet Events (Kafka)

Kafka

Tweeting itself still works — the Tweet Service writes to Cassandra first. But timelines freeze, search indexing stops, and notifications halt until Kafka recovers.

Fan-out Dispatcher

Worker

Users notice nothing immediately — tweets still persist. But the fan-out pipeline stalls: non-celebrity tweets never reach followers' timelines until the dispatcher recovers.

Timeline Store (Cassandra)

Cassandra

Timeline reads for users not in the Redis cache fail — cold starts, dormant users returning, and cache evictions all turn into errors. Already cached feeds keep working.

Timeline Cache (Redis)

Redis

Timeline reads slow down dramatically but don't break — every request now falls through to the durable Timeline Store (Cassandra). Page load times jump from ~3ms to ~15ms.

Typeahead Service

REST API

Typeahead suggestions stop working entirely — users see no autocomplete dropdown. Full-text search (an independent service) is unaffected.

Trie Shard Cluster

gRPC Service

Typeahead degrades noticeably — the Redis cache still serves hot prefixes from its 5-minute TTL, but any miss that would fall through to the trie fails. After the cache drains, all suggestions disappear.

Notification Worker

Worker

Notifications stop arriving entirely — no in-app feed updates and no push notifications. The engagement actions (likes, retweets) themselves succeed without issue.

Notification Store (DynamoDB)

DynamoDB

The notification feed in the app goes blank — users see no historical notifications. Push notifications that were already delivered remain on the device, and new likes/retweets still complete.

//Active Recall

Test Yourself

If you can answer these without scrolling back up, the architecture is yours. Try each one out loud before revealing.

//Go Deeper

Further Reading

//A Word

From the Creator

Every great system starts as a sketch on a whiteboard. The ability to zoom out and see the whole picture (how services connect, where data flows, what breaks and why) is what separates engineers who build features from engineers who build systems. This diagram is more than boxes and arrows. It's a map of decisions, trade-offs, and intentional design.

Studying architectures isn't just about passing interviews. It's about training your intuition. The more systems you take apart, the better you get at sensing where a monolith will crack, where a queue belongs, or when a cache is hiding a deeper problem. You start seeing patterns instead of chaos.

So keep reading, keep tracing those edges, keep asking "why this way and not that way." The engineers who truly understand large systems are the ones who never stop being curious about how things fit together. That curiosity is the only ingredient that really matters.

Atharva Arbat@arbat_atharva

//Explore

More Patterns