0% completed
Designing Instagram
On This Page
What is Instagram?
Try it yourself
Sketch it here
Designing Instagram (video)
Step 1: Clarify the Requirements
Step 2: Estimate the Scale
Step 3: Define the API
Step 4: Define the Data Model
Step 5: Draw the High-Level Design
Step 6: Go Deep
How big is the metadata?
Separate reads from writes
Durability and redundancy
Data sharding
Ranking and News Feed generation
News Feed creation with sharded data
Cache and load balancing
Step 7: Bottlenecks and Failure Points
Where AI Fits in This Design
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.
Jeremiah Stones
· 14 days ago
"The system should be highly reliable; any uploaded photo or video should never be lost."
"Data should be 100% reliable. If a user uploads a photo, the system will guarantee that it will never be lost."
"NoSQL stores, in general, always maintain a certain number of replicas to offer reliability."
"Reliability and Redundancy"
All of these places are using the word reliability or reliable to mean durable. Durable is a much more precise word here, since we are talking about not losing data. Reliability is a broader concept about the system behaving correctly and consistently over time, including when components fail. Technically reliability is not incorrect in any of these sentences but durability is what each sentence is directly referring to.
**D
Piyush Kuhikar
· a month ago
Every Upload Needs Two Writes
To upload a photo:
Step 1:
Get new PhotoID
Step 2:
Store photo metadata
Even with:
Odd IDs DB
Even IDs DB
We then still have 2 write bottlenecks.
Historically, a centralized ID generator (or database sequence server) is a valid solution, but it introduces additional dependencies and scaling limits. Today I'd use Snowflake-style 64-bit IDs or ULIDs so application servers can generate globally unique IDs independently, eliminating the need for a dedicated ID-generation database while still providing sortable identifiers.
Ben
· 2 months ago
I really have to say that those videos are a little hard to watch. The videos are really long and are feeling little uncoordinated. I would prefer hard focused videos what matches exactly the topic of the chapter. For instance, when i want to check a solution to the design task of Instagram, read vs write heavy systems should only be mentioned, especially because there's a chapter on it in this course.
Łukasz Rola
· 2 months ago
I think the section about content publishing and the celebrity use case mixes two different topics: how clients receive feed updates, such as polling, long polling, or WebSockets, and how the feed is generated, such as fanout-on-write vs fanout-on-read.
As I understand it, the celebrity problem is mostly about feed generation: pushing one celebrity post into millions of followers’ feeds can be very expensive.
rout.jatin
· a year ago
When one celebrity user writes new post , it will be visible to all its followers. For example some influencers or celebrity users having million followers , in that case how the system will handle the use case . We can go with pul model on demand like read fanout or we can push the data into distributed queues. I have this thought, but I need more clarity on it
Nathan MANZAMBI NDONGALA
· 2 years ago
Dear [Course Instructor],
Thank you for this course—the content is perfect! I truly appreciate the effort that went into it.
I have one suggestion regarding the System Design Problem section. It would be helpful if the problem descriptions included all key assumptions upfront. For example, when practicing capacity estimation, I often want to compare my assumptions with yours to see if we arrive at the same values. If these assumptions were explicitly stated in the problem description, it would make the process smoother and more structured.
This way, when reviewing the solution, I could focus on understanding your approach rather than searching for assumptions within the explanation.
Thanks again for the great content!
Best regards,
Sourav Singh
· 2 years ago
Is there any discussion as to how Instagram decide on suggesting people to follow. I have seen it could be random but there is a pattern like:
- User in your contact
- User in your friend list follow them
- User who are celebrity
- User with large follower
- User whose content you regularly watch but don't follow.
Is there any system design on how they implement this? Or any similar kind of discussion?
Szymon
· 2 years ago
Please improve this design topic by explaining how schema for 'UserNewsFeed' table would look like.
julian_humecki
· 2 years ago
See title
Cadence chen
· 3 years ago
In the design, it said the photo will be store for 10 years, what do we do with the photos after 10 years? Do we transfer to other server?
Reading Progress
0%
On This Page
What is Instagram?
Try it yourself
Sketch it here
Designing Instagram (video)
Step 1: Clarify the Requirements
Step 2: Estimate the Scale
Step 3: Define the API
Step 4: Define the Data Model
Step 5: Draw the High-Level Design
Step 6: Go Deep
How big is the metadata?
Separate reads from writes
Durability and redundancy
Data sharding
Ranking and News Feed generation
News Feed creation with sharded data
Cache and load balancing
Step 7: Bottlenecks and Failure Points
Where AI Fits in This Design