Photo-sharing combines media handling (heavy I/O), social graph (consistency challenges), and feed serving (scale challenges). Here’s how to design it.
Functional requirements
- Upload photos / videos.
- Follow / unfollow.
- See home timeline (feed of follows’ posts).
- See profile timeline.
- Like, comment, save.
- Search.
Non-functional
- Read-heavy (~100:1).
- Sub-second feed render.
- Eventual consistency OK on follow propagation.
- Petabytes of media at scale.
Architecture
Client
↓ direct upload (signed URL)
S3 (raw)
↓ event
Image processor (variants: thumbnail, 720p, 1080p, 4K)
↓
S3 (processed) + DB row
↓
CDN (CloudFront / Cloudflare)
↓ serve
Client
Plus the social side:
Post → Kafka → fanout workers → user feed entries (Redis sorted sets)
Upload pipeline
- Client requests signed S3 upload URL from API.
- Client uploads directly to S3 (bypasses your servers; saves bandwidth).
- S3 emits
ObjectCreatedevent to SNS / EventBridge. - Image-processor worker picks up event:
- Decode (PIL / Sharp / native).
- Generate variants (thumbnails, sizes, formats).
- Upload variants to S3.
- Insert DB row with metadata.
- Mark post as ready; enqueue fanout to feeds.
Image processing
- Sizes: 150×150 (thumb), 480w, 720w, 1080w, 1920w. Crop to common aspect ratios.
- Formats: WebP (modern), AVIF (smaller), JPEG (fallback).
- HEIC input: from iOS; convert at processing time.
- EXIF: strip for privacy unless explicitly preserved.
Run on K8s with autoscaling, or use serverless (Lambda + Sharp). For massive volume, GPU-accelerated processing pays off.
Feed (timeline)
Hybrid fanout (same as Design Twitter ):
- Normal users: fanout-on-write to followers’ Redis sorted sets.
- Celebrities (>1M followers): fanout-on-read.
- Feed = merge precomputed timeline + recent posts from celebs followed.
Read home timeline:
base = Redis ZREVRANGE timeline:{user_id} (precomputed)
celeb_recent = for each celeb followed: their last 50 posts
merged = merge_by_time(base + celeb_recent)
paginate cursor-style
Follows
CREATE TABLE follows (
follower_id BIGINT,
followee_id BIGINT,
created_at TIMESTAMPTZ,
PRIMARY KEY (follower_id, followee_id)
);
CREATE INDEX follows_followee ON follows (followee_id, follower_id);
For celebrities with 100M followers, this table partitioned by follower_id hash.
When user A follows user B:
- Insert row.
- For B’s recent posts (last 50), inject into A’s timeline (cheap backfill).
- For new B posts going forward, A is in the fanout list.
When unfollow: similar in reverse, lazy clean.
Likes / comments
- Likes: counter in Redis (write-behind to durable). Per-post
likesRedis hash; per-userliked_postsset. - Comments: append-only, per-post in DB. Cassandra-style at scale.
Search
- Hashtags: indexed in Postgres FTS or Elasticsearch.
- Users: indexed by username.
- Discovery: ML-driven recs from engagement features.
See Design a Search System .
Storage and CDN
Images: ~1 MB each at high quality. 100M uploads/day = 100 TB/day. Tier:
- Hot (last 30 days): S3 Standard.
- Warm (30–365 days): S3 IA.
- Cold: S3 Glacier.
CDN at the edge serves 95%+ of bytes. Origin only on cache miss.
Capacity arithmetic
- 200M DAU × 5 photos viewed = 1B views/day.
- At 500 KB avg per view from CDN: 500 TB/day egress.
- Mostly served from cache; origin pulls maybe 1–5 TB/day.
The CDN cost dominates everything.
Common interview probes
- Hot post (10M likes/hour)? Counter shards across Redis nodes; aggregate periodically.
- Delete a post? Soft-delete in DB; CDN cache TTL handles staleness; eventual hard-delete cleans S3.
- Inappropriate content? ML moderation pipeline before publish; user reporting; manual review queue.
- Multi-region? Per-region storage + CDN; eventual replication of metadata.
Read this next
- Design Twitter / News Feed
- Design YouTube / Video Streaming
- Caching Strategies in 2026
- Distributed Systems Fundamentals
If you want a small “Insta-clone” reference (uploads + feeds), it’s at rajpoot.dev .
Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .