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 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 Facebook’s Newsfeed
Designing Facebook’s Newsfeed
Quiz - Designing Facebook’s Newsfeed
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 Instagram
availability
databases
distributed systems
api design
+2
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 Instagram?
Instagram is a social networking service. Users upload photos and videos and share them with other users. A user can share content publicly or privately. Private content is visible only to a chosen set of people.
We will design a simpler version of Instagram. In our version, a user can upload photos and follow other users. The system builds a News Feed for each user. The News Feed shows the top photos from all the people the user follows.
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
Designing Instagram (video)
Here is a video discussing how to design Instagram:
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.
Functional requirements
- Users can upload, download, and view photos.
- Users can search photos by title.
- Users can follow other users.
- The system generates a News Feed for each user. The feed contains top photos from all the people the user follows.
Non-functional requirements
- High availability. The service must stay up, even when servers fail.
- Low latency on the feed. News Feed generation should take at most 200ms.
- Consistency can be relaxed. If a user does not see a new photo for a while, that is fine. We accept this in exchange for availability.
- High durability. Once a photo or video is uploaded successfully, it must never be lost.
Not in scope: adding tags to photos, searching photos by tags, commenting on photos, tagging users in photos, and follow suggestions.
Two observations shape the whole design. The system is read-heavy. Users view photos far more often than they upload them. So the design must retrieve photos quickly. Also, users can upload as many photos as they like. So the system must manage storage efficiently.
Step 2: Estimate the Scale
Ask the interviewer for the size of the user base and the upload rate. Assume 500 million total users, with 1 million daily active users. Assume 2 million new photos per day, with an average photo file size of 200 KB.
Load.
2M / 86,400 seconds = ~23 new photos per second
Photo storage.
2M x 200KB = 400 GB per day
400 GB x 365 days x 10 years = ~1425 TB
One number changes the design: 1425 TB. Photo files are far too big to store as database rows. They need their own storage, which step 4 picks. Everything else about the load is modest.
Step 3: Define the API
Five endpoints cover the four functional requirements.
POST /photos
body: { user_id, photo_data, title }
201: { photo_id, photo_url }
GET /photos/{photo_id}
200: the photo file
GET /photos/search?query=<title>
200: a list of matching photos
POST /follow
body: { follower_id, followee_id }
204: no content
GET /feed/{user_id}
200: the top photos from the people the user follows
The feed endpoint has the 200ms latency target. Step 6 shows how that feed is built.
Step 4: Define the Data Model
The data splits into two kinds with very different shapes.
- Photo files. Large binary objects, about 200 KB each. A file is written once, read many times, and never edited.
- Metadata. Small rows that describe users, photos, and follow relationships.
That split decides the storage. Photo files go into a distributed file storage system like HDFS or S3. The metadata goes into database tables: User, Photo, and UserFollow.
One read pattern matters most: fetch the latest photos from the people a user follows. That query will drive the schema, the photo IDs, and the sharding.
💡 Defining the database schema early in the interview helps you understand the data flow between the parts of the system. It also guides the data partitioning discussion later.
We store data about users, their uploaded photos, and the people they follow. Three tables cover it: User, Photo, and UserFollow.
Photo holds one row per uploaded photo. PhotoPath is the path to the file in object storage; the 200 KB file itself never enters a database row. The location fields and the creation date complete the row. The table needs an index on (PhotoID, CreationDate), because the News Feed fetches recent photos first.
UserFollow stores the follow relationship as a pair of UserIDs: the follower and the followee. User holds one row per account.
The three tables look like this:
How big should PhotoID be? A 32-bit int holds about 2.1 billion values, and we expect far more photos than that:
2M x 365 days x 10 years = ~7.3 billion photos
So PhotoID must be a bigint, a 64-bit integer column, which takes 8 bytes. UserID can stay a 4-byte int, because 500 million users fit comfortably.
Which database? A straightforward choice is a relational database like MySQL, since we need joins between users, photos, and follows. But relational databases are hard to scale to this size. The SQL vs. NoSQL lesson covers that trade in detail.
The alternative is a distributed key-value store, a NoSQL database that maps one key to one value. All photo metadata can go into one table there. The key is the PhotoID. The value is an object holding PhotoLocation, UserLocation, CreationTimestamp, and similar fields.
NoSQL stores scale across many machines easily. They also keep a set number of replicas of every row, which gives durability without extra work. Deletes are not applied instantly. A deleted row is retained for a certain number of days to support undeleting, then removed permanently.
Step 5: Draw the High-Level Design
At a high level, we support two scenarios: uploading photos, and viewing or searching photos. So our service needs object storage servers to store the photo files. It also needs database servers to store the metadata.
Read the diagram as two paths. An upload writes the photo file to object storage and the photo's metadata to the database. A view or search reads metadata from the database, then fetches the photo file from object storage.
Step 6: Go Deep
How big is the metadata?
Let's size each table for ten years. Assume each int and dateTime field takes four bytes.
User. Each row is 68 bytes:
UserID (4 bytes) + Name (20 bytes) + Email (32 bytes) + DateOfBirth (4 bytes)
+ CreationDate (4 bytes) + LastLogin (4 bytes) = 68 bytes
500 million x 68 bytes = ~32 GB
Photo. With the 8-byte bigint PhotoID, each row is 288 bytes. The 256-byte path to the file in object storage takes most of that:
PhotoID (8 bytes) + UserID (4 bytes) + PhotoPath (256 bytes)
+ PhotoLatitude (4 bytes) + PhotoLongitude (4 bytes)
+ UserLatitude (4 bytes) + UserLongitude (4 bytes)
+ CreationDate (4 bytes) = 288 bytes
2M x 288 bytes = ~0.6 GB per day
2M x 288 bytes x 365 days x 10 years = ~1.9 TB
UserFollow. A follow relationship is just two 4-byte UserIDs, so each row is 8 bytes. Assume each user follows 500 people on average:
500 million users x 500 follows x 8 bytes = ~1.82 TB
Total metadata for ten years:
32 GB + 1.9 TB + 1.82 TB = ~3.8 TB
Notice the gap: about 3.8 TB of metadata against 1425 TB of photo files. The files are the real storage problem, and object storage holds them.
Separate reads from writes
Photo uploads (writes) are slow, because they have to go to the disk. Reads are fast, especially when they are served from a cache.
Slow uploads create a second problem: connections. Web servers have a connection limit. Assume a server can hold at most 500 concurrent connections. Each upload is slow, so it occupies its connection for a long time. If uploads fill all 500 connections, the server cannot serve any reads.
The fix is to split reads and writes into separate services. Dedicated servers handle uploads. Different dedicated servers handle reads. Now a burst of slow uploads can never block photo views. The split also lets us scale and optimize each side independently.
The diagram below shows the split:
Durability and redundancy
The requirements say an uploaded photo must never be lost. That is durability, so we store multiple copies of each file. If one storage server dies, we read the photo from a copy on a different storage server.
The same principle applies to every part of the system. We run multiple replicas of each service. If a few instances die, the system stays available. Redundancy removes the single point of failure, meaning any one part whose death would stop the whole system.
Some services must run as a single instance at a time. For those, we run a standby secondary copy beside the primary. The secondary serves no traffic while the primary is healthy. When the primary fails, the secondary takes control. This pattern is called active-passive redundancy. The switch itself is called a failover, and it can happen automatically or through manual action.
The diagram below shows redundancy at every layer of the design:
Data sharding
The metadata will grow to about 3.8 TB, and the read load on it is heavy. One database server cannot serve that alone. So we shard the metadata, meaning we split it across many database servers. If one shard holds 1 TB, four shards would cover 3.8 TB. For better performance and future growth, we keep 10 shards.
Option a: shard by UserID. Find the shard number by UserID % 10 and store the user's data there. This keeps all photos of a user on the same shard. Each shard runs its own auto-incrementing sequence for PhotoIDs. We append the shard number to each PhotoID, which makes the combined ID unique across the whole system.
What are the problems with this scheme?
- Hot users. A hot user is one whose photos a large number of people view. Every photo they upload causes heavy read traffic on that single shard.
- Some users store far more photos than others. Storage spreads unevenly across the shards.
- Some users may not fit on one shard. Spreading one user across shards can raise latency.
- All of a user's data sits on one shard. If that shard is down or under high load, all of that user's data is unavailable or slow.
Option b: shard by PhotoID. Generate a unique PhotoID first. Then find the shard number by PhotoID % 10. Each user's photos now spread across all shards, so every problem above disappears. We also no longer need to append a shard number, because the PhotoID is already unique.
How can we generate PhotoIDs now? We cannot use per-shard auto-increment, because we need the ID before we can pick a shard. One solution is a separate database instance dedicated to generating IDs. It holds one table with a single 64-bit ID column. To add a photo, we insert a row there and use the returned ID as the PhotoID.
Wouldn't that ID database be a single point of failure? Yes, it would. The fix is to run two such databases. One generates even IDs, the other odd IDs. In MySQL, this configuration defines the two sequences:
KeyGeneratingServer1:
auto-increment-increment = 2
auto-increment-offset = 1
KeyGeneratingServer2:
auto-increment-increment = 2
auto-increment-offset = 2
A load balancer alternates between the two servers and skips one that is down. One server may generate more IDs than the other. That causes no problem, because every ID is still unique. We can extend this design with separate ID tables for users or other objects in the system.
Alternatively, we can pre-generate IDs the way the TinyURL Key Generation Service does. KGS creates keys ahead of time and marks them used before handing them out. No insert then waits on ID generation or a collision check.
How can we plan for future growth? Create a large number of logical partitions, many more than we have machines. In the beginning, several logical partitions share one physical database server. When one server holds too much data, we migrate some of its logical partitions to another server. A config file (or a separate database) maps each logical partition to its physical server. To move a partition, we update that map.
The diagram below puts every part together: the read and write split, the caches, the sharded metadata, and the object storage.
Ranking and News Feed generation
The News Feed needs the latest, most popular, and most relevant photos from the people a user follows. Assume the feed shows the top 100 photos.
The direct approach builds the feed at request time. The application server gets the list of people the user follows, then fetches each person's latest 100 photos. A ranking algorithm picks the top 100 by recency, likes, and similar signals. The problem is latency. Querying multiple tables, then sorting, merging, and ranking the results on every request makes the 200ms target hard to meet.
Pre-generate the News Feed instead. Dedicated servers continuously generate users' feeds and store them in a UserNewsFeed table. When a user opens their feed, we query this one table and return the results. The heavy work happens in the background, where nobody is waiting.
To refresh a user's feed, a server reads the UserNewsFeed table for the time of the last generation. It then generates new feed data from that time onwards, using the steps above.
How does new feed content reach the user?
1. Pull. Clients pull the feed from the server at a regular interval, or manually. Two problems. New photos are not shown until the client pulls. And most pulls return an empty response, because nothing new exists.
2. Push. The server pushes new content to users as soon as it is available. To receive pushes, each user keeps a long-poll request open with the server. The problem is a celebrity with millions of followers. Each upload fans out, meaning the server delivers one update per follower. That is far too many pushes.
3. Hybrid. The deciding factor is the poster's follower count. Accounts with a very high number of followers move to a pull model. Their posts are fetched and merged in when a feed is built. All other accounts stay on push. Another form caps push frequency for everyone, and users with many updates pull the rest.
For a detailed discussion of feed generation, see Designing Facebook's Newsfeed.
News Feed creation with sharded data
The feed needs the latest photos first, so we need an efficient sort by creation time. The solution is to make creation time part of the PhotoID itself. We keep a primary index on PhotoID, so finding the latest PhotoIDs becomes quick. No extra metadata query is needed.
Use epoch time, the number of seconds counted from a fixed start date. A PhotoID then has two parts: the epoch time first, then an auto-incrementing sequence from our ID-generating database. To make a new PhotoID, take the current epoch second and append the next sequence number. The shard number is still PhotoID % 10.
How big is this PhotoID? Count the seconds our epoch part must cover for the next 50 years:
86,400 seconds/day x 365 days x 50 years = ~1.6 billion seconds
Storing 1.6 billion values takes 31 bits. We average 23 new photos per second, so a few sequence bits would do. We allocate 9 bits, which allows 2^9 = 512 new photos per second. The extra bits are deliberate: 31 + 9 = 40 bits, an even 5 bytes. The sequence resets every second, and the whole ID fits easily in our 64-bit bigint column.
We use the same technique in Designing Twitter.
Cache and load balancing
Our users are spread around the world, and photos are large. So push the content closer to the users. A CDN (content delivery network) is a large set of geographically distributed cache servers. It serves each photo from a server near the viewer. The Caching lesson covers the details.
Metadata needs its own cache. Put Memcache in front of the database to hold hot rows. Application servers check the cache before they query the database. LRU (evict the least recently used entry) is a reasonable eviction policy here. It discards the row nobody has viewed for the longest time.
How can we build a more intelligent cache? Apply the eighty-twenty rule: 20 percent of the daily photo reads generate 80 percent of the traffic. A small set of photos is so popular that most people view them. So cache 20 percent of the daily read volume of photos and metadata, and most reads never reach the database.
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 caches, the metadata shards, and object storage. Feed pre-generation and ID generation can both be down, and photo views keep working. Uploads stop only if both ID-generating databases fail at once.
- A viral photo still concentrates reads. PhotoID sharding spreads each user's photos, but one popular photo lives on one shard. The metadata cache and the CDN serve most of that traffic.
- Pre-generated feeds lag reality. A new photo appears in followers' feeds only after the next refresh. That is exactly the consistency trade we accepted in step 1.
Where AI Fits in This Design
After the main design, interviewers often ask one more question: where would AI fit in this system?
Step 1 left photo tags and tag search out of scope. AI can bring them back without asking users to type anything. A tagging model looks at each new photo and produces words that describe it, such as beach, dog, or wedding. Run it right after the upload path stores the photo, on the write side, where nobody is waiting.
The interesting part is what happens to the output. The tags are written to the metadata database as ordinary rows. From that moment they are just data. The search API already matches photo titles; pointing it at the tags as well lets it find photos whose titles say nothing. Feeds, sharding, and caching never notice the change. This is the general rule: a model's output becomes part of the data model, and every existing feature can query it.
A moderation classifier, a model that flags photos that break the rules, fits the same place. It scores each new photo before the feed generators can include it.
ID generation, sharding, and feed delivery stay AI-free. They are counting and routing problems, and rules do them well.
💡 In the interview: spend your time on the read and write split, the sharding choice, and feed generation. Two moments give the interviewer the most information. The first is when you name the hot-user problem and switch from UserID sharding to PhotoID sharding. The second is when you name the celebrity fan-out problem and propose the hybrid push and pull model. Both show the same skill: you find the failure in your own first answer. If you are asked what breaks first, say feed staleness, and name the consistency trade you agreed on in step 1.
Key takeaway: Instagram is a read-heavy system with two kinds of data. Photo files are large and never change, so they belong in replicated object storage. Metadata rows are small, so they belong in a sharded database. Separate read services from write services, so slow uploads never block fast views. Shard by PhotoID rather than UserID to avoid hot users. Make PhotoIDs a 64-bit bigint that starts with epoch time, so the newest photos sort first by primary index. Pre-generate each feed into a UserNewsFeed table. Push updates for ordinary accounts, and pull posts of very high-follower accounts at feed build time. Cache the popular 20 percent of photos and metadata, evicting with LRU.
Discussion
On This Page