Question Breakdowns

Photo Sharing

A worked system design: upload, store, and serve photos at scale (think Instagram). Direct-to-blob uploads, thumbnail generation, CDN delivery, and the metadata + feed side.


A photo sharing app lets users upload images and lets others view them fast, anywhere. Like Video Streaming but lighter, it cleanly separates the bytes (storage + delivery of image files) from the metadata (who posted what, likes, feeds). The bytes side is a textbook application of Handling Large Blobs; the metadata side is a read-heavy service.

1. Requirements

Functional:

  • Upload photos; store originals.
  • Serve photos quickly in multiple sizes (thumbnail, feed, full).
  • Browse photos in a feed / on profiles.

Non-functional:

  • Fast delivery — images load instantly, globally.
  • Scale — billions of photos; read-heavy (viewed far more than uploaded).
  • Durable — never lose a user's photos.
  • Cost-aware — storing billions of images is the dominant cost.

2. Don't send bytes through your servers

The first and most important decision: image files do not pass through your app servers. Uploads go directly to blob storage (S3-style object store) via a presigned URL:

client → API: "I want to upload" → returns presigned URL + photo_id
client → PUT image bytes directly to blob storage (not via app server)
client → API: "upload done" → app records metadata, triggers processing

Your servers only ever handle small metadata. Blob storage is durable, effectively infinite, and cheap — the right home for the originals.

3. Generating sizes (thumbnails)

Serving a 5 MB original into a tiny feed thumbnail wastes bandwidth. On upload, an async job (long-running task off a queue) generates several renditions — thumbnail, feed-size, full — and stores each in blob storage:

upload done → enqueue "process image" → resize into {thumb, feed, full} → store each → mark ready

The client then requests the size it needs. This is cheap, parallelisable, and keeps the hot feed light.

4. Delivery: CDN in front

Serving billions of image reads from the origin is wasteful. Put a CDN in front of blob storage so images cache at edges near viewers (Handling Large Blobs). Images are immutable (a photo never changes), so they cache essentially forever with no invalidation worry — most reads never touch your origin. This is what makes global, instant loading feasible.

viewer → CDN edge → (cache hit) image
                  → (miss) fetch from blob store once, cache, serve

5. The metadata side

Separately, a database holds the small stuff: photo id, owner, caption, blob URLs for each size, timestamps, like counts. This service is read-heavy, so cache it and shard by user. Feeds (whose photos you see) are the News Feed problem — a feed stores photo ids, and viewing resolves them to CDN image URLs.

6. Deep dives

  • Cost tiering: move rarely-viewed originals to cold/archival storage; keep popular renditions hot. Dedup identical uploads by content hash.
  • Resumable uploads: chunked/resumable upload for large photos on flaky mobile networks.
  • Access control: private photos need signed, expiring CDN URLs so a leaked link doesn't grant permanent access.
  • Processing failures: if rendition generation fails, retry from the stored original — it's the source of truth for the bytes.
  • EXIF / moderation: strip location EXIF for privacy; run moderation in the same async pipeline.

What to emphasise

Separate bytes from metadata; lead with direct-to-blob + CDN:

"I'd keep the image bytes completely out of my app servers: uploads go directly to blob storage via presigned URLs, and an async job generates thumbnail/feed/full renditions. Delivery is via a CDN in front of blob storage — images are immutable so they cache at the edge essentially forever, which is what makes billions of reads feasible without hitting the origin. Separately, a read-heavy metadata service holds captions, likes, and the blob URLs per size, sharded by user, and the feed stores photo ids that resolve to CDN URLs. Private photos use signed expiring URLs, and I'd tier cold originals to cheap storage for cost."


Next up: Activity Tracker — ingesting time-stamped events from many devices.