Instagram is a social media platform focused on sharing photos and short videos. Users can upload media, apply filters, add captions, follow other users, and engage through likes, comments, and direct messages.
Loading simulation...
Over time, it has expanded to include features such as stories, reels, live streaming, and recommendations.
In this chapter, we will walk through the high-level design of a photo-sharing platform like Instagram.
While Instagram supports a wide range of features including direct messaging, Reels, and Stories, this article will primarily focus on the core functionality of photo and video sharing.
Let’s start by clarifying the requirements.
Before diving into the design, lets outline the functional and non-functional requirements.
The diagram below maps the major components and their connections, from the clients and API Gateway through the core services, data stores, and CDN.
Users interact with the platform through web browsers or mobile apps. The client applications handle video playback, user interactions like likes and comments, and UI rendering, communicating with backend services through an API Gateway or Load Balancer.
Acts as the single entry point for all client requests. It distributes incoming traffic across multiple service instances for high availability and scalability, and enforces rate limiting, authentication, and authorization before forwarding requests to downstream services.
Stores and manages user authentication, profile data, and social connections (follow/unfollow).
Handles photo/video uploads and stores metadata such as caption, user info, and timestamps. It coordinates the upload of media files from the user's device to Object Storage (e.g., AWS S3) and updates metadata in a database. It also uses a message queue such as Kafka to notify the Feed Service when a new post is created.
Precomputes and stores user feeds in a high-performance cache such as Redis or Memcached to enable fast retrieval, and queries the database if a feed is not cached.
Manages likes, comments, and shares, and writes engagement data to a high-throughput database asynchronously via a message queue.
Allows users to search for other users, hashtags, and posts. It uses Elasticsearch to index and retrieve data quickly, and supports autocomplete and full-text search for a better user experience.
Decouples services and enables event-driven processing. It notifies the Feed Service of new posts and updates engagement data asynchronously.
Photos and videos are stored in distributed object storage such as S3 or Google Cloud Storage, and a CDN (Cloudflare, AWS CloudFront) ensures fast delivery globally.
A large-scale content platform like Instagram requires handling both structured data (e.g., user accounts, post metadata) and unstructured/semistructured data (e.g., photos, videos, search indexes).
Typically, you’ll combine multiple database solutions to handle different workloads.
Given the requirements, we will use a relational database (e.g., PostgreSQL, MySQL) for structured data and a NoSQL database (Cassandra, DynamoDB, or Elasticsearch) for feed storage and search indexing.
Given the structured nature of user profiles and posts metadata, a relational database (like PostgreSQL or MySQL) is often well-suited.
While relational databases are ideal for structured data, they struggle with high-velocity writes and large scale distributed workloads. NoSQL databases like Cassandra, DynamoDB, or Redis provide horizontal scalability and high availability.
To reduce feed generation latency, a denormalized feed table stores precomputed timelines:
This table is updated asynchronously via Kafka when a user posts, and cached in Redis for quick retrieval.
To support complex relationship queries, such as mutual friends, suggested followers, and influencer ranking, we can use a graph database like Neo4j or Amazon Neptune.
They efficiently model follower-following relationships with nodes and edges.
Example Query: "People You May Know"
This allows real-time friend suggestions without complex SQL joins.
To support fast and scalable search queries, we can use Elasticsearch, a distributed, real-time search engine optimized for full-text searches.
Each user profile and post metadata can be stored as a document in an Elasticsearch index, allowing quick lookups and advanced filtering.
To support trending hashtags and keyword searches, we can store hashtags in a separate Elasticsearch index.
Example:
Instagram handles petabytes of photos/videos, requiring a durable and low-latency storage solution.
A distributed object storage system, such as Amazon S3, is well-suited for storing media files. It supports pre-signed URLs, enabling users to upload media directly without routing through application servers, reducing load and latency.
To ensure high durability, media files are stored in multiple replicas across different data centers, protecting against data loss.
To further optimize read latency, content can be cached closer to users using a Content Delivery Network (CDN) like Cloudflare or Amazon CloudFront. This reduces load times and improves the user experience, especially for frequently accessed media.
Fetching a user's profile requires a valid JWT token; the response returns core account fields including follower and following counts.
Response:
A POST to the follow endpoint records the relationship between the authenticated user and the target account, and no request body is required.
This endpoint accepts multipart form data so that both caption text and media files can be submitted in a single request.
Form Data:
Response:
This endpoint retrieves the full metadata for a single post, including media URLs, like count, and comment count.
Response:
Paginated via page and limit query parameters, this endpoint returns a personalized list of posts from accounts the authenticated user follows.
Response:
Sending a POST to this endpoint records a like from the authenticated user on the specified post, with no request body needed.
Posting a comment requires a JSON body containing the comment text; the endpoint accepts application/json as the content type.
Comments are returned in paginated order; each item includes the commenter's ID, username, text content, and timestamp.
Response:
A GET request with the q query parameter returns matching user profiles ranked by relevance, powered by Elasticsearch under the hood.
Response:
Since users follow both normal users and celebrities, the system must mix posts efficiently.
For normal users with a manageable number of followers, we use fan-out-on-write, meaning posts are pushed to followers’ feeds at the time of posting.
Example: LPUSH - Add Post to Followers’ Feeds
Suppose user 12345 (John Doe), who has 500 followers, posts a new photo. The Feed Service pushes this post to all 500 followers' feeds.
Here, John's post is pushed to the feeds of followers 56789, 67890, and 78901, along with 497 other followers.
Example: Fetching a User’s Feed (LRANGE - Get Recent Posts)
Benefits: Reads are fast since followers' feeds are pre-loaded, and the approach works well for small and medium-sized accounts.
Challenges: It becomes inefficient for users with millions of followers, such as celebrities. Writing a single post requires copying it to potentially millions of timelines, which leads to high write amplification.
For celebrities and influencers, where a single post may need to reach millions of followers, preloading into every follower’s feed is impractical.
Instead, a fan-out-on-read (pull model) is used.
Benefits: It avoids massive write operations, which keeps the system scalable, and it serves fresh data when users request their feeds.
Challenges: Read latency is slightly higher than the push model, and it requires caching optimization to reduce database lookups.
"john_doe" or "#travel").The Engagement Service processes like, comment and share requests.
It sends a Kafka event to update the DB asynchronously.
Like event:
Share event:
Comment event:
To optimize the latency for popular posts, we can cache like / share count and top comments.
Scalability ensures the system can handle increasing load without degrading performance.
Use distributed databases like Cassandra or DynamoDB to spread data across nodes, and deploy multiple instances of each service behind a load balancer to handle user requests.
Shard large datasets to split them across nodes:
user_id mod Npost_id mod Nfollower_id mod NBreak the system into independent services such as the Feed Service, Post Service, and User Service to improve maintainability and scalability. Use message queues like Kafka or RabbitMQ to handle high-throughput operations asynchronously, including notifications, updates, and feed generation.
Availability ensures that Instagram remains accessible 24/7, even in the face of failures. Given its global user base, the platform must achieve atleast 99.99% uptime.
Maintain replicated databases across multiple regions, such as PostgreSQL replicas and Cassandra multi-region clusters, and deploy multiple application servers across different availability zones (AZs).
Use automatic failover in databases, such as a leader-follower setup in PostgreSQL or multi-leader Cassandra clusters, and implement circuit breakers to gracefully degrade service if a dependency fails.
Durability ensures that data, especially user-generated content (photos, videos, comments, likes), is never lost, even in case of system failures.
Store media in Amazon S3 or Google Cloud Storage, which replicates data across multiple locations to prevent loss.
Use multi-region replication across Cassandra, DynamoDB, or PostgreSQL replicas for disaster recovery, and perform regular backups to prevent accidental data loss.
Implement WAL in databases so that changes are recorded before they are committed, and use event sourcing to log user actions like new posts and likes so that state can be rebuilt if necessary.
20 quizzes