System Design
Learn System Design
Introduction to System Design
How to Learn System Design?
Key Characteristics of Distributed Systems
Scalability
Availability
Latency and Performance
Concurrency and Coordination
Monitoring and Observability
Resilience and Error Handling
Fault Tolerance vs. High Availability
Flashcards Review
Chapter Assessment
Network Essentials
HTTP vs. HTTPS
TCP vs. UDP
HTTP: 1.0 vs. 1.1 vs 2.0 vs. 3.0
URL vs. URI vs. URN
What Happens When You Type a URL into the Browser
Flashcards Review
Chapter Assessment
Long-Polling vs. WebSockets vs. Server-Sent Events
Introduction to Real-Time Communication
What is Long-Polling?
What is WebSocket?
What are Server-Sent Events?
Difference Between Long-Polling, WebSockets, and Server-Sent Events
Flashcards Review
Chapter Assessment
Domain Name System (DNS)
Introduction to DNS
DNS Resolution Process
DNS Load Balancing and High Availability
Flashcards Review
Chapter Assessment
Proxies
What is a Proxy Server?
Uses of Proxies
VPN vs. Proxy Server
Flashcards Review
Chapter Assessment
Load Balancing
Introduction to Load Balancing
Load Balancing Algorithms
Uses of Load Balancing
Load Balancer Types
Stateless vs. Stateful Load Balancing
High Availability and Fault Tolerance
Scalability and Performance
Challenges of Load Balancers
Flashcards Review
Chapter Assessment
API Gateway
Introduction to API Gateway
Usage of API gateway
Advantages and disadvantages of using API gateway
Flashcards Review
Chapter Assessment
API Design
What Is an API?
What Are REST APIs?
Resources, Not Actions
HTTP Methods and Their Semantics
URL Design
Request and Response Shapes
Status Codes and Error Design
Pagination from the Consumer's View
Idempotency Keys
Versioning and Backward Compatibility
Concurrency and Conditional Requests
REST vs gRPC vs GraphQL
Flashcards Review
Chapter Assessment
Rate Limiting and Throttling
What Is Rate Limiting
Rate Limiting Algorithms
Distributed Rate Limiting
Rate Limiting in Practice
Flashcards Review
Chapter Assessment
Caching
Introduction to Caching
Why is Caching Important?
Types of Caching
Cache Replacement Policies
Cache Invalidation
Cache Read Strategies
Cache Coherence and Consistency Models
Caching Challenges
Cache Performance Metrics
Flashcards Review
Chapter Assessment
CDN
What is CDN?
Origin Server vs. Edge Server
CDN Architecture
Push CDN vs. Pull CDN
Flashcards Review
Chapter Assessment
Data Partitioning
Introduction to Data Partitioning
Partitioning Methods
Data Sharding Techniques
Benefits of Data Partitioning
Common Problems Associated with Data Partitioning
Flashcards Review
Chapter Assessment
Redundancy and Replication
What is Redundancy?
What is Replication?
Replication Methods
Data Backup vs. Disaster Recovery
Flashcards Review
Chapter Assessment
CAP & PACELC Theorems
Introduction to CAP Theorem
Components of CAP Theorem
Trade-offs in CAP Theorem
Examples of CAP Theorem in Practice
Beyond CAP Theorem
System Design Trade-offs in Interviews
Flashcards Review
Chapter Assessment
Databases (SQL vs. NoSQL)
Introduction to Databases
SQL Databases
NoSQL Databases
SQL vs. NoSQL
ACID vs BASE Properties
Real-World Examples and Case Studies
SQL Normalization and Denormalization
In-Memory Database vs. On-Disk Database
Data Replication vs. Data Mirroring
Database Federation
Flashcards Review
Chapter Assessment
Indexes
What are Indexes?
How a B-Tree Index Works
Types of Indexes
B-Tree vs. LSM Tree
Indexes in Distributed Systems
Flashcards Review
Chapter Assessment
Bloom Filters
Introduction to Bloom Filters
Benefits & Limitations of Bloom Filters
Variants and Extensions of Bloom Filters
Applications of Bloom Filters
Flashcards Review
Chapter Assessment
Quorum
Why Quorum?
What is Quorum?
Flashcards Review
Chapter Assessment
Leader and Follower
What is Leader and Follower Pattern?
Flashcards Review
Chapter Assessment
Heartbeat
What is Heartbeat?
Flashcards Review
Chapter Assessment
Checksum
What is Checksum?
Uses of Checksum
Flashcards Review
Chapter Assessment
Distributed Messaging System
Introduction to Messaging System
Introduction to Kafka
Messaging patterns
Popular Messaging Queue Systems
RabbitMQ vs. Kafka vs. ActiveMQ
Scalability and Performance
Flashcards Review
Chapter Assessment
Distributed File Systems
What is a Distributed File System?
Architecture of a Distributed File System
Key Components of a DFS
Flashcards Review
Chapter Assessment
Security
What is Security and Privacy?
What is Authentication?
What is Authorization?
Authentication vs. Authorization
OAuth vs. JWT for Authentication
What is Encryption?
What are DDoS Attacks?
Flashcards Review
Chapter Assessment
Misc Concepts
Batch Processing vs. Stream Processing
XML vs. JSON
Synchronous vs. Asynchronous Communication
Push vs. Pull Notification Systems
Microservices vs. Serverless Architecture
Message Queues vs. Service Bus
Stateful vs. Stateless Architecture
Event-Driven vs. Polling Architecture
Flashcards Review
Chapter Assessment
Quiz - System Design Fundamentals
Quiz
System Design Trade-offs
Importance of Discussing Trade-offs
Strong vs Eventual Consistency
Latency vs Throughput
ACID vs BASE Properties in Databases
Read-Through vs Write-Through Cache
Batch Processing vs Stream Processing
Load Balancer vs. API Gateway
API Gateway vs Direct Service Exposure
Proxy vs. Reverse Proxy
API Gateway vs. Reverse Proxy
SQL vs. NoSQL
Primary-Replica vs Peer-to-Peer Replication
Data Compression vs Data Deduplication
Server-Side Caching vs Client-Side Caching
REST vs RPC
Polling vs. Long-Polling vs. WebSockets vs. Webhooks
CDN Usage vs Direct Server Serving
Serverless Architecture vs Traditional Server-based
Stateful vs Stateless Architecture
Hybrid Cloud Storage vs All-Cloud Storage
Token Bucket vs Leaky Bucket
Read Heavy vs Write Heavy System
Quiz
How to Approach a System Design Interview
System Design Interviews - A step by step guide
Functional vs. Non-functional Requirements
What are Back-of-the-Envelope Estimations?
Things to Avoid During System Design Interview
System Design Master Template
System Design Master Template
Quiz
Designing a URL Shortening Service like TinyURL
Designing a URL Shortening Service like TinyURL
Quiz - Designing URL Shortner
Designing Pastebin
Designing Pastebin
Quiz - Designing Pastebin
Designing Instagram
Designing Instagram
Quiz - Designing Instagram
Designing Dropbox
Designing Dropbox
Quiz - Designing Dropbox
Designing Facebook Messenger
Designing Facebook Messenger
Quiz - Designing Facebook Messenger
Designing Twitter
Designing Twitter
Quiz - Designing Twitter
Designing Youtube or Netflix
Designing Youtube or Netflix
Quiz - Designing Youtube
Designing Typeahead Suggestion
Designing Typeahead Suggestion
Quiz - Designing Typeahead Suggestion
Designing an API Rate Limiter
Designing an API Rate Limiter
Quiz - Designing an API Rate Limiter
Designing Twitter Search
Designing Twitter Search
Quiz - Designing Twitter Search
Designing a Web Crawler
Designing a Web Crawler
Quiz - Designing a Web Crawler
Designing Yelp or Nearby Friends
Designing Yelp or Nearby Friends
Quiz - Designing Yelp or Nearby Friends
Designing Uber backend
Designing Uber backend
Quiz - Designing Uber backend
Designing Ticketmaster
Designing Ticketmaster
Quiz - Designing Ticketmaster
Dynamo: How to design a key value store?
Dynamo: Introduction
High-Level Architecture
Data Partitioning
Replication
Vector Clocks and Conflicting Data
The Life of Dynamo’s put() & get() Operations
Anti-entropy Through Merkle Trees
Gossip Protocol
Dynamo Characteristics and Criticism
Summary: Dynamo
Quiz: Dynamo
Mock Interview: Dynamo
Designing YouTube Likes Counter (medium)
YouTube Likes Counter
Quiz
Cassandra: How to Design a Wide-column NoSQL Database?
Cassandra: Introduction
High-level Architecture
Replication
Cassandra Consistency Levels
Gossiper
Anatomy of Cassandra's Write Operation
Anatomy of Cassandra's Read Operation
Compaction
Tombstones
Summary: Cassandra
Quiz: Cassandra
Mock Interview: Cassandra
Kafka: How to Design a Distributed Messaging System?
Messaging Systems: Introduction
Kafka: Introduction
High-level Architecture
Kafka: Deep Dive
Consumer Groups
Kafka Workflow
Role of ZooKeeper
Controller Broker
Kafka Delivery Semantics
Kafka Characteristics
Summary: Kafka
Quiz: Kafka
Mock Interview: Kafka
Chubby: How to Design a Distributed Locking Service?
Chubby: Introduction
High-level Architecture
Design Rationale
How Chubby Works
File, Directories, and Handles
Locks, Sequencers, and Lock-delays
Sessions and Events
Master Election and Chubby Events
Caching
Database
Scaling Chubby
Summary: Chubby
Quiz: Chubby
Mock Interview: Chubby
HDFS: How to Design File Storage System?
Hadoop Distributed File System: Introduction
High-level Architecture
Deep Dive
Anatomy of a Read Operation
Anatomy of a Write Operation
Data Integrity & Caching
Fault Tolerance
HDFS High Availability (HA)
HDFS Characteristics
Summary: HDFS
Quiz: HDFS
Mock Interview: HDFS
GFS: How to Design a Distributed File System Storage?
Google File System: Introduction
High-level Architecture
Single Master and Large Chunk Size
Metadata
Master Operations
Anatomy of a Read Operation
Anatomy of a Write Operation
Anatomy of an Append Operation
GFS Consistency Model and Snapshotting
Fault Tolerance, High Availability, and Data Integrity
Garbage Collection
Criticism on GFS
Summary: GFS
Quiz: GFS
Mock Interview: GFS
BigTable: How to Design a Wide Column Storage System?
BigTable: Introduction
BigTable Data Model
System APIs
Partitioning and High-level Architecture
SSTable
GFS and Chubby
Bigtable Components
Working with Tablets
The Life of BigTable's Read & Write Operations
Fault Tolerance and Compaction
BigTable Refinements
BigTable Characteristics
Summary: BigTable
Quiz: BigTable
Mock Interview: BigTable
Designing Reddit (medium)
Design Reddit
Quiz
Designing Notification Service (medium)
Designing a Notification System
Quiz
Design Google Calendar (medium)
Design Google calendar (Medium)
Quiz
Design a Recommendation System (medium)
Design a Recommendation System for Netflix
Quiz
Designing Gmail (medium)
Design Gmail
Quiz
Designing Google News (medium)
Design Google News, a Global News Aggregator System (Medium)
Quiz
Designing Unique ID Generator (medium)
Design Unique ID Generator (Easy)
Quiz
Designing Code Judging System (medium)
Design Code Judging System like LeetCode (Medium)
Quiz
Designing Payment System (hard)
Design Payment System
Quiz
Designing Flash Sale System (hard)
Design a Flash Sale for an E-commerce Site (Hard)
Quiz
Designing Reminder Alert System (hard)
Design a Reminder Alert System
Quiz
System Design Patterns
Introduction: System Design Patterns
1. Bloom Filters
2. Consistent Hashing
3. Quorum
4. Leader and Follower
5. Write-ahead Log
6. Segmented Log
7. High-Water Mark
8. Lease
9. Heartbeat
10. Gossip Protocol
11. Phi Accrual Failure Detection
12. Split Brain
13. Fencing
14. Checksum
15. Vector Clocks
16. CAP Theorem
17. PACELC Theorem
18. Hinted Handoff
19. Read Repair
20. Merkle Trees
Quiz
Designing Facebook’s Newsfeed
api design
distributed systems
messaging patterns
availability
+3
Every case study in this chapter follows the same seven steps from System Design Interviews: A step by step guide, and builds its design from the components in the System Design Master Template. Keep both open beside you, and try each problem yourself before reading the solution.
What is Facebook's Newsfeed?
A Newsfeed is the constantly updating list of stories in the middle of Facebook's homepage. It includes status updates, photos, videos, links, app activity, and likes. These come from the people, pages, and groups that a user follows. Together they form a scrollable record of a user's own life and their friends' lives.
Every social network needs some form of newsfeed. Twitter, Instagram, and Facebook all show updates from friends and followed accounts. Designing Twitter and Designing Instagram only sketch the feed. This lesson designs it in full.
The hard part is timing. Do we build a user's feed when they ask for it, or before they ask? Push vs Pull Architecture introduces that trade-off. Here we apply it to a complete design.
Try it yourself
Before reading the solution, try designing it. Aim to produce four things: the requirements, a rough load estimate, the API, and a first drawing of the components.
Sketch it here
Step 1: Clarify the Requirements
💡 Always clarify requirements at the beginning of the interview. Ask questions until you know the exact scope of the system the interviewer has in mind.
We will design a newsfeed for Facebook with these requirements:
Functional requirements
- The newsfeed is generated from the posts of the people, pages, and groups that a user follows.
- A user may have many friends and follow a large number of pages and groups.
- Feed items may contain images, videos, or just text.
- New posts are appended to the newsfeed as they arrive, for all active users.
The fourth requirement makes the feed a live stream, not a static page. A new post must reach the feeds of active users without them reloading everything.
Non-functional requirements
- Real-time generation. The system should generate any user's newsfeed in real time. The maximum latency seen by the end user should be 2 seconds.
- Fresh posts. A new post should reach a user's feed within 5 seconds, assuming a new newsfeed request comes in.
These two numbers measure different things. The 2-second target starts when a user asks for their feed. The 5-second target starts earlier, when a post is created. It covers the write path. The post has to be picked up, ranked, and added to the follower's feed before that feed is served again.
Step 2: Estimate the Scale
Ask the interviewer for the base numbers first. Assume the average user has 300 friends and follows 200 pages.
Those 500 accounts are what a reader follows. They set the size of the feed we build for that reader. How many followers a poster has is a different number. It decides the cost of delivering that poster's posts, and step 6 depends on the difference.
Traffic. Assume 300 million daily active users, each fetching their timeline five times a day.
300M x 5 fetches = 1.5B newsfeed requests per day
1.5B / 86,400 seconds = ~17,500 requests per second
Storage. Assume we keep about 500 posts of every user's feed in memory, for a quick fetch. Assume each post is about 1 KB.
500 posts x 1 KB = 500 KB per user
500 KB x 300M users = 150 TB of memory
150 TB / 100 GB per server = ~1,500 machines
Why is a post only 1 KB when feeds contain images and videos? The 1 KB is the post record: its text and its metadata. Photos and videos are stored separately, in blob storage. Blob storage is storage built for large binary files. The client fetches the media on its own, so the feed cache holds only the small post record.
Two of these numbers change the design:
- 17,500 feed requests per second, each merging posts from about 500 accounts. That is too much work to do while the user waits. Feeds must be built ahead of time.
- 150 TB of memory. The stored feeds do not fit on one machine. The feed cache must be partitioned across about 1,500 servers.
Step 3: Define the API
We can expose the service through REST APIs. The call that matters most is fetching the newsfeed:
getUserFeed(api_dev_key, user_id, since_id, count, max_id, exclude_replies)
Parameters:
api_dev_key(string): the API developer key of a registered account. We use it, among other things, to throttle users based on their allocated quota.user_id(number): the ID of the user for whom the system will generate the newsfeed.since_id(number): optional. Returns results with an ID higher than (that is, more recent than) the specified ID.count(number): optional. The number of feed items to try to retrieve, up to a maximum of 200 per request.max_id(number): optional. Returns results with an ID less than (that is, older than) or equal to the specified ID.exclude_replies(boolean): optional. Prevents replies from appearing in the returned timeline.
Returns: (JSON) a JSON object containing a list of feed items.
The two ID parameters cover both directions of scrolling. since_id pages toward newer posts, and max_id pages toward older ones.
Step 4: Define the Data Model
There are three primary objects: User, Entity (a page or a group), and FeedItem (a post). The relationships between them are simple:
- A User can follow other entities and can become friends with other users.
- Both users and entities can post FeedItems. A FeedItem can contain text, images, or videos.
- Each FeedItem has a UserID that points to the User who created it. For simplicity, we assume that only users create feed items. On Facebook, Pages can post feed items too.
- Each FeedItem can optionally have an EntityID. It points to the page or group where the post was created.
If we use a relational database, we need to model two relations: User to Entity, and FeedItem to Media. Each user can be friends with many people and follow many entities. So we store the follow relation in a separate table, UserFollow. Its Type column records whether the followed ID is a User or an Entity. Similarly, a FeedMedia table links each FeedItem to its media. Each media file also gets a Media row, which holds the file's metadata.
One more record appears in the schema, but it is not a table. It is the pre-generated feed entry that the system keeps in memory, one per user. Step 2 already argued for it: feeds must be built ahead of time. The schema below shows the tables and that in-memory record:
User and Entity hold the profiles. A User row is one person: name, email, and a few dates. An Entity row is a page or a group, and its Type column records which of the two it is. Both tables grow only when new accounts appear, so they stay small.
The UserFollow table is the one to study. EntityOrFriendID can point at a user or at an entity, and Type says which one. The feed query in step 6 filters on that column. One row records one follow. The average reader from step 2 therefore adds about 500 rows here. With 300 million users, UserFollow outgrows every other table in the schema.
FeedItem is the post record that step 2 priced at about 1 KB: the text plus its metadata. UserID names the author, and the optional EntityID names the page or group it was posted in. NumLikes is a like counter. Ranking in step 6 reads it when it scores a post.
Media files are not in any of these tables. A Media row holds only the file's metadata and its Path, a reference to the file itself, which lives in blob storage. A FeedMedia row links one post to one media row. A post with three photos therefore has three FeedMedia rows.
The last record in the diagram lives in memory, not in the database. It is the pre-generated feed: one entry per user, holding that user's ready feed items in order. It is derived data: every item in it is a copy built from the tables above. If it is lost, the tables can rebuild it. Step 6 defines its exact structure, keyed by UserID, and shards it across the 1,500 cache servers from step 2.
Step 5: Draw the High-Level Design
At a high level, this problem divides into two parts: generating a feed and publishing it.
Feed generation. A newsfeed is generated from the posts of the users and entities that a user follows. Say we receive a request to generate the feed for a user named Jane. We perform these steps:
- Retrieve the IDs of all users and entities that Jane follows.
- Retrieve the latest, most popular, and most relevant posts for those IDs. These are the candidate posts for Jane's newsfeed.
- Rank these posts based on their relevance to Jane. This ranked list is Jane's current feed.
- Store this feed in the cache and return the top posts (say 20) to be rendered on Jane's screen.
- When Jane reaches the end of her current feed, the client fetches the next 20 posts from the server, and so on.
Notice that we generated the feed once and stored it in the cache. What about new posts from people Jane follows? If Jane is online, we need a way to rank those new posts and add them to her feed. The simple way is to rerun the steps above at short intervals, then notify Jane that newer items are waiting. A timer alone cannot meet the 5-second target from step 1, so step 6 adds a faster path for live updates.
Feed publishing. Whenever Jane loads her newsfeed page, she requests and pulls feed items from the server. When she reaches the end of her current feed, she pulls more. For newer items there are two options. The server can notify Jane, and she pulls. Or the server can push the new posts to her. Step 6 compares these options.
Components. At a high level, the Newsfeed service needs these parts:
- Web servers: maintain a connection with the user. This connection carries data between the user and the server.
- Application servers: run the workflow of storing new posts in the database servers. Other application servers retrieve the newsfeed and push it to the end user.
- Metadata database and cache: store the metadata about Users, Pages, and Groups.
- Posts database and cache: store metadata about posts and their contents.
- Video and photo storage, and cache: blob storage for all the media included in the posts.
- Newsfeed generation service: gathers and ranks all the relevant posts for a user, generates the newsfeed, and stores it in the cache. This service also receives live updates and adds newer feed items to any user's timeline.
- Feed notification service: notifies the user that newer items are available for their newsfeed.
The diagram below is the high-level architecture of the system. In it, User B and User C follow User A.
Read the diagram from the poster's side. User A creates a post, and the application servers store it in the posts database. Users B and C follow A, so the newsfeed generation service adds A's post to their stored feeds. The feed notification service then tells B and C that new items are waiting.
Step 6: Go Deep
Generating the feed
Take the simplest case first. The newsfeed generation service fetches the most recent posts from all the users and entities that Jane follows. The query would look like this:
(SELECT FeedItemID FROM FeedItem WHERE UserID in ( SELECT EntityOrFriendID FROM UserFollow WHERE UserID = <current_user_id> and type = 0(user)) ) UNION (SELECT FeedItemID FROM FeedItem WHERE EntityID in ( SELECT EntityOrFriendID FROM UserFollow WHERE UserID = <current_user_id> and type = 1(entity)) ) ORDER BY CreationDate DESC LIMIT 100
The two SELECT statements come from the two kinds of follow. The first finds posts by followed users, matching on UserID. The second finds posts in followed pages and groups, matching on EntityID. UNION merges the two result sets into one list, which is then sorted by creation date.
This design has four problems:
- It is very slow for users with a lot of friends and follows. We have to sort, merge, and rank a huge number of posts on demand.
- We generate the timeline when the user loads their page. That adds latency to every page load.
- For live updates, each new post causes feed updates for all followers. That could create high backlogs in the newsfeed generation service.
- For live updates, pushing (or notifying about) newer posts to users could create very heavy loads. That is especially true for people or pages that have a lot of followers.
The first two problems share a cause: we do the work while the user waits. To fix that, we pre-generate the timeline and store it in memory.
Offline generation. Dedicated servers continuously generate users' newsfeeds and store them in memory. When a user requests their feed, we serve it from the pre-generated, stored copy. The feed is compiled in the background on a regular basis, not on load.
Whenever these servers generate the feed for a user, they first check when that user's feed was last generated. Then they generate new feed data from that time onwards. We store this data in a hash table. The key is UserID. The value is a struct like this:
Struct { LinkedHashMap<FeedItemID, FeedItem> feedItems; DateTime lastGenerated; }
We store the FeedItemIDs in a structure like a LinkedHashMap or a TreeMap. Both keep the items in order and let us jump to any item by its ID. That combination is what pagination needs. When a user wants more feed items, the client sends the last FeedItemID it currently shows. We jump to that ID in the map and return the next batch of items from there.
How much feed to keep in memory
How many feed items should we store per user? Start with 500, then adjust from the usage pattern. Suppose one page of a feed shows 20 posts, and most users never browse more than ten pages. Then 200 posts per user covers almost everyone. A user who wants more posts than we hold in memory is served by a query to the backend servers.
20 posts per page x 10 pages = 200 posts per user
Should we generate and keep feeds for all users? Many users do not log in often, and their pre-generated feeds waste memory. There are two options. 1) The simple option is an LRU cache. LRU (evict the least recently used entry) removes users who have not accessed their newsfeed for a long time. 2) A smarter solution learns each user's login pattern and pre-generates their feed just before they are likely to be active. Useful inputs are the time of day a user is active, and the days of the week they open their feed.
Publishing the feed
Publishing means getting a new post into the feeds of everyone who follows the poster. Pushing one post to all followers is called fan-out. So the push approach is called fan-out-on-write, and the pull approach is called fan-out-on-load.
Keep the two roles from step 2 apart here, because they are easy to confuse. The cost of fan-out-on-write depends on the poster. One post becomes one write per follower the poster has. The size of a feed depends on the reader. It is built from every account the reader follows. Our average reader follows about 500 accounts, which is manageable. But some posters have millions of followers, and that is where fan-out gets expensive.
1. Pull model, or fan-out-on-load. Keep all recent feed data in memory. Users pull it from the server whenever they need it. Clients can pull on a regular schedule, or manually. This has two problems. New data is not shown until the client issues a pull request. And it is hard to find the right pull interval. Most pulls return an empty response when there is no new data, which wastes resources.
2. Push model, or fan-out-on-write. Once a user publishes a post, we immediately push it to all their followers. The advantage is on the read side. When fetching a feed, we do not have to go through the reader's follow list and fetch posts for each account. That significantly reduces read operations. To receive pushes, each user maintains a long poll request with the server. Long polling means the client keeps a request open, and the server answers it only when new data exists. The problem is a poster with millions of followers (a celebrity user). One post means the server has to push updates to millions of people at once.
3. Hybrid. Combine fan-out-on-write and fan-out-on-load, and choose per poster. Stop pushing posts from users with a very high number of followers. Only push posts from users who have a few hundred (or thousand) followers. For celebrity users, let their followers pull the updates. Disabling fan-out for those few posters saves a huge number of resources. When a reader loads their feed, the system takes the stored list and merges in recent posts from the few celebrities they follow.
Two more variants are worth knowing. Once a user publishes a post, we can limit the fan-out to only their online friends. And we can combine "push to notify" with "pull for serving". The server pushes a small signal that new posts exist, and the client pulls the posts. A pure push or a pure pull model is less versatile than these combinations. Push vs Pull Architecture covers the general trade-off, and Designing Twitter applies it to a timeline.
How many feed items can we return per request? Set a maximum for one request. A typical page is 20 items, and the API caps count at 200. Within that limit, let the client specify how many it wants. A mobile client and a desktop client show different numbers of posts.
Should we always notify users about new posts? Notifying is useful. But on mobile devices data is relatively expensive, and pushed data can consume unnecessary bandwidth. So at least for mobile devices, we can choose not to push the data. Instead, users "Pull to Refresh" to get new posts.
Ranking the feed
The simplest ranking is by creation time. Modern ranking algorithms do a lot more, to make sure "important" posts rank higher. The idea is to select key signals that make a post important, then combine them into a ranking score. A signal is a feature of a post that we can measure.
Useful signals include the number of likes, comments, and shares, the time of the update, and whether the post has images or videos. A score computed from these features is enough for a simple ranking system. A better system evaluates itself constantly. It checks whether changes improve retention (how often users come back) and ad revenue.
Partitioning the data
Sharding posts and metadata. We have a huge number of new posts every day, and the read load is extremely high. So we distribute the data across many machines to read and write it efficiently. For the databases holding posts and their metadata, use the same sharding design as Designing Twitter.
Sharding feed data. The feed data lives in memory, and we partition it by UserID. We pass the UserID to a hash function, which maps the user to one cache server. That server holds all of the user's feed objects. We never expect to store more than 500 FeedItemIDs for one user, so a user's feed always fits on a single server. To get a user's feed, we query only one server. For future growth and replication, use consistent hashing. Consistent hashing means adding or removing a server moves only a small part of the data.
Step 7: Bottlenecks and Failure Points
The interviewer does not expect this design to be limitless. They expect you to know where it ends.
- The read path depends on the feed cache. Every feed request goes to one cache server, found by hashing the UserID. If that server is down and not replicated, every user hashed to it loses their feed. Replicate the feed cache.
- Fan-out cost is set by the poster with the most followers. The hybrid removes the celebrity case from the push path. Without it, one celebrity post would occupy the newsfeed generation service for everyone.
- Pre-generated feeds lag reality. A new post reaches a follower's feed only after fan-out or the next refresh. That lag is what the 5-second target measures.
- 150 TB of memory is the largest cost in the design. Storing 200 items instead of 500, and evicting inactive users, are the two ways to shrink it.
Where AI Fits in This Design
After the main design, interviewers often ask one more question: where would AI fit in this system?
This lesson already ranks the feed with a score built from signals: likes, comments, shares, recency, and whether a post has media. A learned model is the natural next step, predicting which posts a reader will interact with. The interview point is not the model. It is what the model needs from the system.
A model needs its signals at feed-build time, and it needs them fast. Counting likes across the posts database on every build is exactly the work the pre-generation design exists to avoid. The signals get their own store: a table or cache, keyed by post, updated as events arrive, read in bulk when a feed is built. Engineers call this a feature store. It is a genuinely new component, with its own freshness and failure questions, and naming it is what separates a real answer from "add ML".
Everything else stays. Fan-out still decides which posts reach a feed; the model only orders them once they are there. The celebrity rule, the per-user feed cache, and pagination work unchanged.
The lesson already names the second use: learning each user's login pattern, so feeds are pre-generated just before they are needed. The shape is the same: the model schedules the work, and the pipeline does it.
💡 In the interview: spend your time on feed generation and feed publishing, and move quickly through everything else. Say early that building the feed at request time cannot meet the 2-second target, and move to pre-generation. The moment the interviewer is listening for is when you name the celebrity problem and switch to the hybrid. Push for ordinary posters, pull for accounts with millions of followers. Keep the poster and the reader apart when you explain it. Fan-out cost follows the poster's follower count, not the reader's follow list. If you are asked what breaks first, name the cache server that holds a user's only copy of their feed.
Key takeaway: a newsfeed is a read-heavy system where every read merges posts from hundreds of accounts. About 17,500 feed requests per second, each over about 500 followed accounts, cannot be built at request time. Pre-generate each feed offline and keep about 200 to 500 items per user in a LinkedHashMap keyed by UserID. Page through it from the last FeedItemID the client saw. Deliver new posts by fan-out-on-write for ordinary posters and by pull for celebrities, because fan-out cost grows with the poster's follower count. Rank with signals like likes, comments, and recency. Shard the feed cache by UserID with consistent hashing, so a feed read touches one server. Keep media in blob storage, so a cached post stays about 1 KB.
Discussion
On This Page