Design system like Instagram. Instagram is a photo and video sharing social networking platform, if you are not familiar with this App, please spend sometime in using the App.
- User should be able to post photo/videos
- User should be follow other users
- Users should be able to view the photos/videos posted by user which they are following
- Generate timeline for users
Non Functional Requirement
- Should be able to support 1 billion users
- Should be able to support 100 million active users daily
- Should be able to post the photos and followers should be able view the photos
- Read to write ratio is 100 : 1
We can assume that each user will post 5 photos in average with 200KB of size and 100 million active users each day.
5 * 100 * 10 ^6 / 24 * 60 * 60 = 5787 QPS
We can calculate the bandwidth requirement as the size of the each photo is 200KB
Write Bandwidth = 5787 * 200KB / 1024 = 1.1 GBps Read Bandwidth = 1.1 GBps * 100 = 110 GBps
We will be calculating memory requirement for 10 years, as every user will be posting 5 photos each every day with each photo of size of 200 KB and there are 100 million active users daily.
5 * 200 * 100 * 10 ^6 * 10 * 365 = ~331 PB
- Should support write QPS of 5.8 K
- Require Bandwidth of 1.1 GBps write and 110 GBps for read
- Require 331 PB for image storage for 10 years
High Level Design
In high level, we need two services which will be responsible for taking care of Post and User actions.
Low Level Design
As we have identified that there are two components User Service and Post Service.
User service responsibilities
- Should be able to store user and follower details
- Should be able to provide user and follower information
User data model will have userId as primary/unique key and need a separate entity for tracking the user follower details
Post service responsibility
- Should accept photos from user and store it in DB
- Should be able to serve the photos of followers
I often see that people design a single service for serving read and write queries, most of the cases it should be fine. But incase of high performance application, it is always better to separate read and write loads, which allows scale both of them independently, it is also called as Command Query Responsibility Segregation pattern.
We can store the Post metadata and images in separate DB. It always good idea to store the LargeObjects like image, video and multimedia in object based storage. Object storage provides scalability, availability and reliability. Object storage uses replication mechanism to avoid single point of failure. Another main advantage with Object storage is scalability, in future we want to store high quality image and video, then size will not problem.
Post model will have unique Id for each post and userId who owns the post.
We need to identify requirement for each data store and then choose database.
- Should be able to store the User data and Follower
- Should be able to store 1 billion users
We can use any DB which has sharding capability as our data store or we can also apply any sharding strategy on top any datastore, but if the database doesn’t have sharding capability, then it is over ahead. I will always suggest to choose any DB which has sharding capability, in this case any NoSQL DB will work, such as Cassandra, Amazon Dynamo DB and Vitesse (MySQL based sharded DB) also works
- Should be able to store metadata and serve the
As our data is really huge and cannot fit in one machine, we choose any DB with sharding capability. I have discussed the sharding strategy next section.
- Should be able store Binary Large Objects (BLOB)
- Should be able to provide availability and consistency guarantee
Any object based store or file system can used here such as HDFS, Amazon S3 and Azure File Storage etc.,
I will try to address the cache based on the data store. One of the key aspect in sharding is choosing right key for sharding the data. I would recommend to go through the post on sharding, if you are new to sharding
User Data Sharding
We can use userId to shard the data, as it can evenly distribute the data across all the shards.
Post Data Sharding
In case of Post, if we choose userId as sharding and the user is celebrity, then we will end up with hot spotting due to large number of user start to view/search the post of celebrity user.
We can use postId as sharding key as the posts will sharded across the shards, in this case the load spread across the shards, so there is no hot spotting. But drawback is we need to query all the shards for data for a user.
Object Data Sharding
We can use objectId to shard the data and spread the objects evenly across the shards.
We are expecting our users to be distributed across globe. We need a cache service to serve the traffic, otherwise the content generated by users in same region will be served faster than other regions . We can use CDN to cache the data closer to the users physical location.
Another reason to cache, as our read pattern is 100:1, cost will go astronomically high, if we try to scale our object storage without cache. It is always good to cache the data as the images are static once posted. We can identify the query pattern and able to tune our caching logic, as the newly posted content is viewed by everyone, we can cache few days data and serve the traffic.
I will try to cover this in another post, as this itself a separate topic and also shares similar behaviour with Twitter user timeline and Facebook feed generation etc.,