Design Instagram — post, follow, and feed at 500M DAU

Design Instagram

Junior-friendly Instagram walkthrough: create posts, follow, chronological feed — fan-out on read → write → hybrid celebrity, presigned multipart upload, CDN + media variants, and interview bars by level.

Understanding the problem

Instagram is a visual social network. In interviews (Meta and beyond) you're graded on feed generation under follow-graph skew and media upload/delivery at global scale — not rebuilding Reels ranking or Stories.

You post; followers' feeds update via hybrid fan-out; home opens under 500ms.
Post once — normals get a push, celebs get merged on read — home stays snappy.
01Post

Photo/video + caption.

02Follow

Unidirectional graph.

03Feed

Chronological home.

04Media

Presign + CDN.

Pair with Delivery framework, Design News Feed, Design Dropbox, Scaling reads, and Caching.

Functional requirements

Non-functional requirements

Ask scale first — here: 500M DAU, ~100M posts/day.

Core entities

User, Post, Media, and Follow entities.
One Post entity covers both photos and videos — Media is the S3 bytes.
  • User — username, profile stubs.
  • Post — caption, author, pointer to media (photo or video).
  • Media — actual bytes in object storage (S3).
  • Follow — followerId → followedId (uni-directional).

API

One endpoint per FR. Media bytes upload via presigned URL (details in deep dive) — metadata create stays thin.

POST /posts -> { postId, uploadUrl }
{ "caption": "My cool photo!" }
// client uploads bytes to uploadUrl (multipart for large video)

POST /follows
{ "followedId": "123" }
// followerId from auth token

GET /feed?cursor=&limit= -> { posts: Post[], nextCursor }

HLD — create a post

First cut: Post Service writes metadata to a DB and bytes to S3 (we'll evolve to presigned direct upload for large files).

Client through gateway to Post Service, Posts DB and S3.
Create Post — metadata in Posts DB, bytes in S3.
  1. Client POST /posts (caption + media, or caption then upload).
  2. Gateway → Post Service.
  3. Persist post row + object key; return postId.

HLD — follow users

Unidirectional graph: insert (followerId, followedId). A dedicated Follow Service is fine — follow QPS ≪ feed/post QPS.

Follow Service writing to Follows table.
Follow — one row per edge.

HLD — chronological feed (v1)

Fan-out on read: load followees → query each user's recent posts → merge/sort → page with cursor.

Fan-out on read feed generation.
Feed Generation — simple fan-out on read (won't survive 500M DAU).

Pick a store you can index well. DynamoDB works (Follows: PK followerId, SK followedId; Posts: PK userId, SK createdAt#postId). PostgreSQL is also fine — Instagram famously ran Postgres for post metadata; justify either.

Deep dive — feed < 500ms

OK — cache pages

Redis key feed:{userId}:{cursor} → postId list. Reduces DB hits but still fans out on miss; cache must be huge for good hit rate.

Feed service with Redis page cache in front of Posts DB.
Simple cache — treats the symptom, not the architecture.

Good — fan-out on write

On post: enqueue → Fan-out worker loads followers (GSI on followedId) → prepend postId into each follower's Redis ZSET (feed:{userId}, score = timestamp). Read path: ZRANGE top N, then hydrate metadata (hybrid: postId ZSET + short-TTL post HASH; miss → BatchGet → fill cache).

Async fan-out worker writing Redis ZSET feeds; feed service hydrates.
Precomputed feeds — fast reads; write amplification on celebs.

Great — hybrid

Threshold (e.g. 100k followers): push for normals; celebs skip fan-out. On feed read: load Redis timeline + pull recent posts from celebrity followees → chronological merge.

Hybrid fan-out on write for normals and fan-out on read for celebrities.
Hybrid — push normals · pull celebrities.
  • Tune the threshold — too low leaves write amp; too high hurts read merge cost.
  • Users who follow many celebs see slightly slower feeds — set SLAs and cache hot celeb posts.
  • Redis durability: mention AOF + Sentinel/Cluster so feeds aren't a pure memory lottery.

Deep dive — instant media (to 4GB video)

Two problems: upload (chunking, bypass app servers) and download (global latency + right-sized variants).

Upload

POST /posts returns postId + presigned URL; client uses S3 multipart for large video. Post status starts pending; prefer S3 event → worker to mark complete (more reliable than trusting the client PATCH).

Presigned multipart upload to S3 with completion event updating Posts DB.
Upload — bytes never traverse Post Service.

Serve — bad → good → great

Client downloading media directly from S3.
Direct S3 — simple, high latency far from the bucket region.
Client through CDN edge to S3 origin.
CDN — global PoPs; still one resolution for every device.
Media pipeline generating variants served via CDN.
CDN + variants (WebP, resolutions, ABR video) — best UX, more storage/pipeline cost.

Deep dive — 500M DAU napkin

  • Media: 100M posts × ~2MB ≈ 200TB/day → ~750PB over 10 years — S3 + lifecycle to Glacier for cold.
  • Metadata: 100M × ~1KB ≈ 100GB/day — archive cold rows if DynamoDB/SQL cost bites.
  • Throughput: horizontal scale services behind LB; hybrid feed + CDN are the real levers.

Storage hierarchy: CDN → Redis → SSD DB → object store → cold tier. Move cold data down the ladder to save money.

Final design

Final Instagram architecture with gateway, post follow feed fan-out, Redis, DynamoDB, S3 and CDN.
Final — hybrid fan-out, Redis feeds, DynamoDB metadata, S3 + CDN variants.

Cost and performance levers

What interviewers expect by level

Architecture by level

Three progressive sketches — beginner spine, mid optimizations, pro production depth. Use the matching diagram in the interview; say the tradeoff out loud.

Beginner Instagram: post, follow, and fan-out-on-read feed.
Beginner architecture

Pros: Covers create / follow / chronological feed with a clear shared DB + S3 split. Cons: Fan-out on read blows up with 1,000 followees — latency and cost won't hit <500ms at 500M DAU.

Mid Instagram: fan-out on write to Redis feeds plus CDN for media.
Mid architecture

Pros: Precomputed Redis ZSET feeds make reads a single fast query; CDN fixes global media latency; presigned uploads keep bytes off app servers. Cons: Celebrity write amplification can melt fan-out workers; Redis without durability/HA is a single point of pain.

Pro Instagram: hybrid fan-out, media variants, Redis HA, cold storage.
Pro architecture

Pros: Hybrid push/pull solves the celebrity problem; variants + CDN match device/network; AOF/Sentinel and Glacier show cost/ops judgment. Cons: Threshold tuning and dual read paths add ops complexity — staff should say when you'd evolve from simple push, not start at hybrid.

Interview takeaway

Mid: spine + push feeds. Senior: hybrid + blobs. Staff: evolution and failure modes.

Wrapping up

Instagram interviews reward the same two muscles as News Feed and Dropbox: skew-aware fan-out and global media plumbing — with napkin math that makes hybrid inevitable.

Related: Delivery framework · Design News Feed · Design Dropbox · Scaling reads · Caching · Redis · Design Ticketmaster.

← Lattice