"Design Instagram" is one of the most common photo-sharing system design questions, and a close cousin of designing Twitter and designing a news feed. The crux is two-fold: storing and serving large media files efficiently through a CDN, and generating each user's feed from the people they follow — without melting under celebrity accounts.
Here's the full Instagram system design walkthrough with a diagram, covering media storage, the metadata model, the follow graph, feed generation, caching, and the trade-offs interviewers probe.
+-----------+ +------------------+
Upload | Client | -----> | API / App Tier |
& Feed +-----------+ +------------------+
| | |
+------------------+ | +-------------------+
v v v
+---------------+ +-----------------+ +-----------------+
| Media Service | | Metadata DB | | Feed Service |
| -> Blob (S3) | | posts, users, | | fanout + cache |
+-------+-------+ | follow graph | +--------+--------+
| +-----------------+ |
v v
+-----------+ +---------------+
| CDN | <----- serves images/video -----------> | Feed Cache |
+-----------+ to clients worldwide | (Redis) |
+---------------+
1. Clarify the requirements
Functional requirements
- Upload photos and videos with a caption
- Follow and unfollow other users
- View a personalized home feed of posts from people you follow
- View any user's profile and their posts
- Like and comment on posts
Non-functional requirements
- Highly available — the feed should always load
- Low latency for feed reads (the app feels instant)
- Eventual consistency is acceptable (a post can take a second to appear)
- Read-heavy: far more feed views and image loads than uploads
Back-of-the-envelope scale: Assume 500M daily active users and ~100M photos uploaded per day. That averages ~1,200 uploads/sec, but reads dominate — call it a 100:1 read-to-write ratio, so millions of feed and media reads per second. At ~2 MB per photo, 100M/day is ~200 TB of new media daily, which is why media storage and the CDN are the heart of the design.
2. API design
Instagram is mostly request/response over HTTPS. The interesting wrinkle is the two-step upload: get a presigned URL, push the bytes straight to blob storage, then create the post record.
# Upload media (client uploads bytes directly to blob storage)
POST /v1/media:initUpload -> { uploadUrl, mediaId }
PUT <presigned blob URL> (raw image/video bytes)
# Create the post once media is stored
POST /v1/posts { mediaId, caption }
GET /v1/users/{id}/posts?cursor= -> profile grid
# Feed and social graph
GET /v1/feed?cursor= -> ranked home feed (paginated)
POST /v1/users/{id}/follow
POST /v1/posts/{id}/like
3. High-level architecture
An upload splits into two paths. The media service hands the client a presigned URL so the raw bytes go straight into blob storage (S3) without passing through the app servers; a CDN sits in front of that storage to cache and serve media from edge locations near each viewer. Separately, a small post record — post ID, author, caption, and the media URL — is written to the metadata database.
Reads are where the volume lives. When a user opens the app, the feed service returns a list of post IDs and metadata; the client then loads the actual images and videos directly from the CDN. Because media is read far more than written, that CDN offload is what keeps the origin store and the app tier from being overwhelmed.
The follow graph drives feed generation: when someone publishes, the feed service decides whose feed should include the post. That decision — push it now or pull it later — is the central trade-off, covered below.
4. Data model & storage
Media (blob storage): images and videos are immutable binary objects in S3-style storage, addressed by a unique key. The CDN caches them. We never store binary blobs in the database.
Metadata DB: a sharded relational or wide-column store holds the small, structured records:
users— id, handle, profile fieldsposts— id, author_id, media_url, caption, created_at (sharded by post ID or author ID)follows— directed edges(follower_id, followee_id), indexed in both directions so we can list a user's followers and the accounts they followlikes/comments— keyed by post ID
Feed cache: each user's precomputed home feed is a list of post IDs held in Redis, so a feed read is a single fast lookup rather than a fan-in query across everyone they follow.
5. News-feed generation: fanout-on-write vs read
This is the question the interviewer most wants you to reason about.
- Fanout-on-write (push). When a user posts, immediately insert the post ID into the feed cache of every follower. Reads are then trivially fast. The cost: a post by someone with millions of followers triggers millions of writes — a write storm.
- Fanout-on-read (pull). Store nothing precomputed; at read time, gather recent posts from everyone the user follows and merge them. Cheap writes, but every feed load is an expensive fan-in query.
The hybrid is the real-world answer. Use push for normal accounts so most feeds are precomputed and instant. For celebrity accounts with huge follower counts, switch to pull: don't fan their posts out at write time; instead, at read time, fetch their recent posts and merge them into the requesting user's feed. This caps the write amplification a single post can cause while keeping the common case fast. The same push/pull tension shows up in designing a chat app's group fan-out.
6. Scaling and bottlenecks
- CDN for all media — the single biggest lever; serve images/video from the edge and keep them out of the app tier entirely.
- Shard the metadata DB by post ID or author ID; add read replicas for hot profiles.
- Feed cache in Redis so a home-feed read is one lookup, not a fan-in across the follow graph.
- Async pipeline (message queue) for fanout, thumbnail generation, and transcoding, so uploads return quickly and heavy work happens in the background.
Key trade-offs the interviewer probes
- Push vs pull fanout. Push gives fast reads but explodes on celebrities; pull is write-cheap but read-expensive. The hybrid — push for most, pull for high-fanout accounts — is the expected answer.
- Consistency. A feed can be eventually consistent: it's fine if a new post takes a second to appear, which buys you the freedom to do fanout asynchronously.
- Storage cost. Media dominates storage. Generate multiple resolutions, serve the smallest that fits the viewport, and tier older media to cheaper cold storage.
Framework reminder: every system design answer follows the same arc — requirements → estimates → API → high-level design → data model → scale → trade-offs. Keep the system design cheat sheet in mind and narrate which stage you're in.
Practice photo-sharing design with live AI support
CoPilot Interview surfaces a structured design skeleton — requirements, API, data model, and scaling — in about 4 seconds during real Zoom and Teams calls. Free for Windows and macOS, invisible on screen-share.
Download freeFAQ
How is photo storage handled in an Instagram system design?
Photos and videos are stored as binary objects in a blob store like Amazon S3, not in a relational database. The database holds only metadata — the post ID, author, caption, and the object's URL — while a CDN caches and serves the actual media close to users for fast loads.
What is fanout-on-write versus fanout-on-read for the news feed?
Fanout-on-write pushes a new post into each follower's precomputed feed at publish time, making feed reads very fast. Fanout-on-read assembles the feed from followed users' posts at request time, which is cheaper to write but slower to read. Instagram uses a hybrid: push for normal accounts, pull for celebrities with millions of followers.
How do you handle celebrity accounts with millions of followers?
Fanning a celebrity's post out to tens of millions of feeds at write time creates a thundering-herd write storm. The fix is a hybrid model: posts from high-follower accounts are pulled in at read time and merged with the precomputed feed, so a single post never triggers a massive write burst.
How is the follow graph stored?
The follow graph is a set of directed edges (follower to followee) stored in a sharded database or a dedicated graph store, with the edges indexed in both directions so you can quickly list a user's followers and the accounts they follow.
Why use a CDN for an Instagram-style app?
Media is the heaviest payload and is read far more often than it is written. A CDN caches images and videos at edge locations near users, cutting latency and offloading the origin blob store, which is what makes the feed feel instant on a global scale.