System Design

Learn System Design

How to Learn System Design?

Scalability

Availability

Latency and Performance

Concurrency and Coordination

Monitoring and Observability

Resilience and Error Handling

Fault Tolerance vs. High Availability

Flashcards Review

Chapter Assessment

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

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

Introduction to DNS

DNS Resolution Process

DNS Load Balancing and High Availability

Flashcards Review

Chapter Assessment

What is a Proxy Server?

Uses of Proxies

VPN vs. Proxy Server

Flashcards Review

Chapter Assessment

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

Introduction to API Gateway

Usage of API gateway

Advantages and disadvantages of using API gateway

Flashcards Review

Chapter Assessment

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

What Is Rate Limiting

Rate Limiting Algorithms

Distributed Rate Limiting

Rate Limiting in Practice

Flashcards Review

Chapter Assessment

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

What is CDN?

Origin Server vs. Edge Server

CDN Architecture

Push CDN vs. Pull CDN

Flashcards Review

Chapter Assessment

Introduction to Data Partitioning

Partitioning Methods

Data Sharding Techniques

Benefits of Data Partitioning

Common Problems Associated with Data Partitioning

Flashcards Review

Chapter Assessment

What is Redundancy?

What is Replication?

Replication Methods

Data Backup vs. Disaster Recovery

Flashcards Review

Chapter Assessment

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

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

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

Introduction to Bloom Filters

Benefits & Limitations of Bloom Filters

Variants and Extensions of Bloom Filters

Applications of Bloom Filters

Flashcards Review

Chapter Assessment

Why Quorum?

What is Quorum?

Flashcards Review

Chapter Assessment

What is Leader and Follower Pattern?

Flashcards Review

Chapter Assessment

What is Heartbeat?

Flashcards Review

Chapter Assessment

What is Checksum?

Uses of Checksum

Flashcards Review

Chapter Assessment

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

What is a Distributed File System?

Architecture of a Distributed File System

Key Components of a DFS

Flashcards Review

Chapter Assessment

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

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

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

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

Quiz

Designing a URL Shortening Service like TinyURL

Quiz - Designing URL Shortner

Designing Pastebin

Quiz - Designing Pastebin

Designing Instagram

Designing Instagram

Quiz - Designing Instagram

Designing Dropbox

Quiz - Designing Dropbox

Designing Facebook Messenger

Quiz - Designing Facebook Messenger

Designing Twitter

Quiz - Designing Twitter

Designing Youtube or Netflix

Quiz - Designing Youtube

Designing Typeahead Suggestion

Quiz - Designing Typeahead Suggestion

Designing an API Rate Limiter

Quiz - Designing an API Rate Limiter

Designing Twitter Search

Quiz - Designing Twitter Search

Designing a Web Crawler

Quiz - Designing a Web Crawler

Designing Facebook’s Newsfeed

Quiz - Designing Facebook’s Newsfeed

Designing Yelp or Nearby Friends

Quiz - Designing Yelp or Nearby Friends

Designing Uber backend

Quiz - Designing Uber backend

Designing Ticketmaster

Quiz - Designing Ticketmaster

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

YouTube Likes Counter

Quiz

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

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: 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

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

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: 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

Design Reddit

Quiz

Designing a Notification System

Quiz

Design Google calendar (Medium)

Quiz

Design a Recommendation System for Netflix

Quiz

Design Gmail

Quiz

Design Google News, a Global News Aggregator System (Medium)

Quiz

Design Unique ID Generator (Easy)

Quiz

Design Code Judging System like LeetCode (Medium)

Quiz

Design Payment System

Quiz

Design a Flash Sale for an E-commerce Site (Hard)

Quiz

Design a Reminder Alert System

Quiz

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

Designing Instagram

availability

databases

distributed systems

api design

+2

hard
·
23 min
·Updated Aug 2026·Credit: Grokking the System Design Interview

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:

Designing 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

  1. Users can upload, download, and view photos.
  2. Users can search photos by title.
  3. Users can follow other users.
  4. The system generates a News Feed for each user. The feed contains top photos from all the people the user follows.

Non-functional requirements

  1. High availability. The service must stay up, even when servers fail.
  2. Low latency on the feed. News Feed generation should take at most 200ms.
  3. 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.
  4. 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.

  1. Photo files. Large binary objects, about 200 KB each. A file is written once, read many times, and never edited.
  2. 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:

Image
The three metadata tables. PhotoID is a bigint, because ten years of uploads is about 7.3 billion photos.

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.

Image
Instagram - High-Level Design

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:

Image
Instagram Component Design

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:

Image
Redundancy in Instagram

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?

  1. 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.
  2. Some users store far more photos than others. Storage spreads unevenly across the shards.
  3. Some users may not fit on one shard. Spreading one user across shards can raise latency.
  4. 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.

Image
Instagram Detailed Design

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
Have a question or insight about this topic? Share it with the community.
Reading Progress
0%

On This Page