System Design

Design Instagram

Photo upload, feed, likes, comments, stories, and object storage at 2B+ users with global CDN delivery.

Interview tip Photos → S3 + CDN thumbnails (multiple sizes). Metadata in Cassandra. Feed uses same hybrid fan-out as news feed. Separate hot path for image bytes vs metadata.

① Functional requirements

  • Upload photo with optional filter applied client-side or server-side
  • Generate thumbnails: 150px, 320px, 640px, 1080px
  • Home feed: photos from followed users, ranked
  • Like and unlike photos; display like count
  • Comment on photos (flat comments, paginated)
  • User profile: grid of user's photos
  • Follow/unfollow users
Out of scope (state in interview)
  • Stories (24h ephemeral)
  • Reels / video (brief mention)
  • Direct messaging
  • Explore/discovery algorithm

② Non-functional requirements

  • Photo upload complete < 5s on 4G
  • Feed load < 2s; images load progressively
  • 99.9% availability on image CDN
  • 100M photos/day (~1.2K uploads/sec)
  • Global low-latency image delivery

③ Back-of-the-envelope scale

Assumptions
  • 100M photos/day → ~1.2K uploads/sec avg, ~5K/sec peak
  • Avg 2MB raw → 200KB JPEG after compression; 4 thumbnail sizes ≈ 400KB total per photo
  • Storage: 100M × 400KB × 365 ≈ 14.6 PB/year (CDN + S3)
  • Feed reads: 2B MAU × 3 sessions × 2 feed loads = 12B/day → ~140K/sec
  • Likes: 10 likes/photo avg → 1B likes/day → ~12K writes/sec
  • Avg 300 followers → fan-out: 1.2K × 300 = 360K feed writes/sec
Store photo IDs in feed cache (not URLs). CDN URLs derived from photo_id + size template. Image processing async — show placeholder until thumbnails ready. Hybrid fan-out for users with > 100K followers.

④ High-level architecture

Instagram Photo Platform
Mobile Clients
API Gateway
Media Service (upload)
Photo Service (metadata)
Feed Service
Social Graph
Image Processing Workers
Fan-out Workers
S3 + CDN
Cassandra (photos, feeds)
Redis (feed cache)
Upload photoS3 rawResize + CDNFan-out feed
Upload flow: presigned S3 URL → client uploads → webhook triggers image workers → multiple sizes to CDN → photo metadata written → fan-out to follower feeds. Client polls or push notification when processing complete.

⑤ Data flow & execution path

End-to-end execution flow
① Client② API / LB③ Core services④ Cache + DB⑤ Message queue⑥ Async workers
Sync path: validate → authorize → read/write primary store
Async path: publish domain events → consumers (email, analytics, search index)
Read-heavy path: CDN / edge cache → regional cache → DB replica
Failure path: retry with backoff, DLQ, idempotent handlers
In interviews, trace one user action through this diagram. State what is synchronous (user waits) vs asynchronous (background), and where you enforce idempotency.

⑥ API & interfaces

Endpoint / flowPurposeNotes
POST /v1/photos/upload-urlGet presigned URLReturns {uploadUrl, photoId, expiresAt}
POST /v1/photos/{id}/completeFinalize uploadTriggers processing; returns status processing|ready
GET /v1/feed?cursor=Home feedPhoto cards with CDN URLs for thumbnails
POST /v1/photos/{id}/likeLike photoIdempotent; async counter increment
GET /v1/photos/{id}/comments?cursor=CommentsPaginated; newest first
POST /v1/photos/{id}/commentsAdd commentReturns commentId; notifies photo owner

⑦ Data model & storage

photos: photo_id, user_id, caption, filter, cdn_paths {150,320,640,1080}, like_count, created_at

likes: photo_id, user_id (composite PK for idempotency)

comments: comment_id, photo_id, user_id, text, created_at
StoreWhatWhy
S3 + CloudFront CDNImage blobs (all sizes)Immutable; cache 1 year; geo-distributed
CassandraPhotos, comments, likesPartition by photo_id; high write throughput
Redis Sorted SetsUser feed cachePhoto IDs ranked by score; hybrid fan-out
KafkaProcessing + fan-out queueDecouple upload from feed update

⑧ Deep dive — core components

Image processing pipeline

On upload complete: worker downloads raw from S3, applies filter (if server-side), generates 4 JPEG sizes with ImageMagick/libvips, uploads each to CDN path /photos/{photo_id}/{size}.jpg. Update photo record status=ready. Typical processing: 2–5 seconds.
Client shows blurred placeholder (LQIP — low-quality image placeholder, 20×20 base64) until ready. Webhook or polling on GET /photos/{id}/status.

Feed with photo metadata hydration

Feed cache stores photo_ids in ranked order. On feed read: batch MGET photo metadata from Cassandra (or local cache). Construct CDN URLs from template — no URL stored per feed entry. Progressive loading: 150px in feed list, 640px on tap.

Like count consistency

Like write: INSERT into likes table (idempotent PK). Async: Redis INCR photo:{id}:likes. Display count from Redis (stale OK by seconds). Periodic reconciliation job syncs Redis → Cassandra like_count. Unlike: DELETE from likes + DECR.

Storage cost optimization

CDN caches hot images at edge — S3 egress minimal. Lifecycle: move originals to Glacier after 90 days if only thumbnails needed. WebP format saves 30% vs JPEG for supported clients. Deduplicate identical uploads via perceptual hash (optional).

⑨ Trade-offs & alternatives

DecisionOption AOption BPick when
FilterClient-sideServer-sideClient saves server CPU; server for consistency
Feed fan-outPush (write)Pull (read)Push for normal; pull for celebrities
Like countEventually consistentStrongly consistentEventual standard for social; strong overkill
Image formatJPEGWebP/AVIFJPEG universal; WebP for bandwidth savings
Comment modelFlat listThreaded treeFlat simpler; threaded for Twitter-style

⑩ 45-minute interview script

  1. 0–5 min: Clarify upload, feed, likes, comments, followers
  2. 5–12 min: Scale — photos/day, storage PB, fan-out math
  3. 12–22 min: Architecture — media, photo, feed, graph services
  4. 22–30 min: Image processing pipeline and CDN strategy
  5. 30–36 min: Hybrid feed fan-out (reuse news feed pattern)
  6. 36–42 min: Like count async increment
  7. 42–45 min: Storage cost and multi-resolution thumbnails

⑪ Likely follow-up questions

QuestionShort answer
Photo upload on slow 3G?Client-side resize before upload; chunked upload; retry with exponential backoff
Celebrity with 50M followers posts?Skip fan-out; pull at read time; merge with precomputed feed
Delete photo?Mark deleted in DB; CDN cache expires via TTL; purge from feeds async
Duplicate photo detection?Perceptual hash on upload; flag or block duplicates
Comments on viral photo (1M comments)?Paginate; cache top comments; rate limit comment writes
Multi-region users?S3 cross-region replication; CDN global; Cassandra multi-DC

⑫ Revision checklist

  • Presigned S3 upload flow
  • Multiple thumbnail sizes (150–1080px)
  • Async image processing workers
  • CDN for all image delivery
  • Feed stores photo IDs not blobs
  • Hybrid fan-out for celebrity users
  • Like idempotency via composite PK
  • Eventually consistent like counts
  • 100M photos/day scale math
  • Progressive image loading strategy
mediaCDNfan-outimage processingCassandra