
Design Twitter for Millions of Users
A microblogging platform with tweet ingestion, hybrid fan-out timelines, typeahead search, and real-time notifications.
A photo and video sharing social platform supporting billions of daily media uploads, personalized feed generation, and real-time engagement.
Denser dots = higher throughput. Hover any edge for its full contract.
Rough, order-of-magnitude numbers. The point is to justify the architecture, not to be exact.
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.
Every social platform starts simple. A stateless Post Service issues pre-signed URLs so clients upload photos directly into S3 — media bytes never touch the API tier. Metadata (caption, user_id, timestamp) lands in a sharded PostgreSQL instance.
Timelines are naive: the client requests recent posts from followed users and the database runs a join across the follow graph. This works for a few thousand users, but every feed read is an expensive multi-table query, and every viewer downloads the full-size original photo — a slow, wasteful experience.
Scale pressure: Views outnumber uploads 200:1 and every feed read joins across the entire follow graph — database queries take seconds for users with thousands of follows
Stop computing feeds at read time. The Post Service now publishes a 'new post' event to Kafka. A Feed Worker consumes it and writes the post ID to every follower's timeline in Cassandra — partitioned by user_id, clustered by created_at, so reading the top N posts is a single sequential scan.
Video uploads get the same decoupling: a Video Transcoder consumes the same event and processes raw videos into multiple renditions asynchronously. The Feed Service (behind its own API Gateway) serves the pre-computed timeline, and the system now scales read traffic without crushing the relational database.
Scale pressure: Likes and comments produce 115K writes/sec at peak — synchronous processing would stall the API servers
Social interactions are write-heavy and latency-tolerant, which makes them a natural fit for the same async pattern. The Engagement Service processes likes, comments, and shares by publishing events to a dedicated Kafka topic. Workers consume these events to update counters in Redis (fast reads) and materialize rows in PostgreSQL (durable storage).
A Search Service backed by Elasticsearch indexes post captions and user profiles for full-text search. The Notification Service consumes engagement events and delivers push notifications via APNs/FCM. Every new subsystem is decoupled by the same queue — the architecture's async backbone.
Scale pressure: Celebrities with 100M followers cause a write explosion — fanning out a single post to every follower's timeline writes 100M rows
Two optimizations finish the architecture. First, a Redis cache in front of the feed timeline stores each user's top 100 post IDs in memory — the hottest reads never touch Cassandra. Second, a hybrid fan-out strategy switches celebrity accounts to fan-in-on-read: their posts are NOT pre-written to followers' timelines; instead, the Feed Service merges them from a dedicated Posts DB at read time.
With these additions, the system handles the full Instagram scale: 500M DAUs, 500M new posts per day, 10B likes, and sub-200ms feed generation for every user — whether they follow 200 people or 200 million.
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.
The write path for a new photo — from client to object storage, with metadata persistence and async jobs.
The read path — how a user's personalized feed is generated and served with sub-200ms latency.
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.
Handles the ingestion and storage of user-uploaded photos and videos. The client requests a pre-signed URL from the Post Service and uploads the media directly to Object Storage (S3). The Post Service saves the metadata (caption, user_id, etc.) in a sharded relational database (PostgreSQL) and publishes a 'new post' event to Kafka to trigger asynchronous processes like feed generation and video transcoding. Video transcoding is handled by a dedicated async worker service that processes the raw video into multiple renditions.
Focuses on serving a user's personalized news feed with low latency (<200ms). A hybrid fan-out approach is used: for normal users with a moderate number of followers, posts are pre-computed and pushed to a Feed Timeline table (Cassandra) and cached in Redis (fan-out-on-write). For celebrity users with millions of followers, posts are fetched on-demand (fan-in-on-read) and merged with the cached feed for the user. The Feed Service retrieves post IDs from the timeline and then fetches the full post metadata, with results served from the Redis cache.
Manages user interactions (likes, comments) and notifications. The Engagement Service asynchronously processes likes and comments via a message queue (Kafka) to update databases and caches. The Notification Service consumes events from Kafka and sends push notifications to users via APNs/FCM. The system uses a sharded relational database for core data (posts, users, comments) and a wide-column store (Cassandra) for feed timelines, optimized for fast sequential reads. Elasticsearch is used for full-text search and indexing of posts and user profiles, with results cached in Redis for performance.
An architecture is a record of trade-offs. For every major choice here: what won, what lost, and why the constraints made it so.
Video and image uploads can be gigabytes in size. If these bytes flowed through the API tier, it would have to scale with media traffic instead of request traffic, making it expensive and slow. Pre-signed URLs offload the bandwidth and latency cost to the object storage, while the API tier only handles small metadata requests. Multipart upload adds resumability for free: a failed chunk retries alone.
Fan-out on write for all users would cause massive write amplification for celebrities with millions of followers — 100M writes per post. Fan-in on read for all users would make feed reads too slow due to many joins per request. The hybrid approach balances this: most users get fast pre-computed feeds from Cassandra/Redis, while celebrity accounts use on-demand reads to avoid the 'write explosion' problem.
To uniquely identify photos and avoid collisions across shards, we need a globally unique ID. Using epoch time as the most significant bits allows sorting photos by time naturally, and an auto-increment sequence ensures uniqueness. This also enables efficient retrieval of recent posts from a specific user through a sequential index scan.
Sharding by UserID keeps all photos of a user on one shard, but creates 'hot spots' for popular users. Sharding by PhotoID with a consistent hash ensures even data distribution and avoids any single shard being overwhelmed by a celebrity's uploads. It also simplifies adding new shards for future growth without rebalancing.
Video transcoding is CPU-intensive, and engagement writes peak at 115K/sec. Processing either synchronously would block the API server and degrade user experience. By decoupling through Kafka, uploads and engagement actions return instantly, the worker fleets scale independently on queue depth, and failed jobs retry without affecting the user-facing API.
The feed timeline workload is write-heavy (fan-out) and requires fast sequential reads of the top N posts — a natural fit for Cassandra's partitioned row storage. PostgreSQL would require complex sharding for the same throughput. Redis lacks the durability and capacity for all users' full timelines, so it works as a cache atop Cassandra, not a replacement.
Reading a system means sensing where it cracks under 10× load. These are the pressure points of this design, and how it holds.
When a celebrity with 100 million followers posts a photo, fan-out-on-write would require 100 million writes to the followers' timelines. This could overwhelm Cassandra and Kafka queues simultaneously, causing backpressure across the entire async pipeline.
The hybrid fan-out approach switches celebrities to fan-in-on-read: their posts are fetched from the Posts DB at read time and merged with the cached feed. This avoids the write spike for popular accounts while keeping read latency under 200ms.
A viral post can receive millions of likes and comments within minutes. The engagement service, notification service, and databases all see a massive surge — enough to saturate connections and cause cascading timeouts.
Kafka decouples ingestion from processing. The Engagement Service writes each action to the queue almost instantly, then workers drain it asynchronously with batching. Redis caches running counts so reads never hit the database during the storm.
Partitioning the feed timeline by user_id spreads load for most users, but a celebrity with millions of followers still creates a single hot partition when their followers read simultaneously.
The Redis cache absorbs nearly all reads for hot keys. For celebrity fan-in, the read path goes to the Posts DB rather than the timeline at all — Cassandra only stores pre-computed timelines for normal users.
With 500M new posts per day, storing and serving petabytes of media becomes extremely expensive, especially serving content directly from blob storage to millions of viewers.
A multi-tiered storage strategy: hot tier (frequently accessed content) and cold tier (older content). A global CDN caches media closer to users, reducing egress costs and latency by 90-95% for cache hits. Direct S3 URLs serve as the fallback for rarely-viewed content.
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.
No new posts can be created — the control plane for uploads is down. Existing posts and feed reads continue working because the read path is independent.
Core functionality breaks: no new posts, no likes, no comments, no follows. Existing feed data cached in Cassandra and Redis remains readable but cannot be updated.
Uploads complete and metadata persists, but videos are never transcoded, feeds never update, and search indexes stall. Creators see confirmation but followers never see the new post.
Every feed request fails — the app shows stale cached content or an empty state. Users cannot discover new posts from followed accounts.
Feeds cannot be read from the primary timeline store. Users see either a degraded empty feed or whatever remains in the Redis cache before entries expire.
Nothing breaks for most users — but every feed read now lands on Cassandra, increasing p99 latency from 1ms to ~12ms. Redis is a cache, not a source of truth.
Likes, comments, and shares appear to succeed (the client gets a 200) but never materialize — counters don't increment, notifications don't send. The system accepts writes but processing halts.
Search returns empty results or errors. Users cannot find posts by caption, hashtag, or search for other users by name.
If you can answer these without scrolling back up, the architecture is yours. Try each one out loud before revealing.
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

A microblogging platform with tweet ingestion, hybrid fan-out timelines, typeahead search, and real-time notifications.
A scalable, highly available cloud file storage and synchronization service.
Cloud-native e-commerce platform on AWS