Everything, under the clock. You'll run a full design for a photo-sharing app (think Instagram), then self-grade against a rubric. The model answer is hidden behind each step — try first, then reveal.
Your turn: list functional + non-functional requirements and explicitly de-scope.
Functional (in scope): upload photo, follow/unfollow, home feed (reverse-chron), like, comment. De-scoped: DMs, stories, search, explore/recommendations — "I'll set these aside unless you'd like one."
Non-functional: read-heavy; feed should load in <200 ms; high availability for reads (a stale feed is fine → AP); durability for photos is critical; eventual consistency acceptable for likes/feed. Global users → low latency worldwide.
Your turn: 100M DAU, 2 uploads/user/day, 20 feed-views/user/day, photo ≈ 1.5 MB.
Writes: 200M/day ≈ 2k uploads/s (~6k peak). Reads: 2B/day ≈ 20k feed reads/s. R:W ≈ 10:1 → read-heavy → cache + replicas + precomputed feeds. Media: 200M × 1.5 MB = 300 TB/day → object store + CDN, tiering for old data; metadata ≈ 200 GB/day → sharded DB. Therefore: blobs in S3, metadata sharded, heavy caching, push-based feeds.
POST /v1/media:initiate → returns a pre-signed S3 URL + media id. POST /v1/posts {media_id, caption} → idempotency-key header. GET /v1/feed?cursor=&limit=20. POST /v1/posts/{id}/likes, POST /v1/posts/{id}/comments, PUT /v1/follows/{userId}. Cursor pagination; auth + rate limiting at the gateway.
Photos in object storage (S3); the DB holds metadata. Tables: users, posts(id, user_id, media_url, caption, created_at), follows(follower,followee), likes, comments. Relational (Postgres) for users/posts with transactional integrity; shard by user_id as it grows (Unit 04). Likes/comment counts denormalized onto the post (eventual consistency — Unit 05). Index posts(user_id, created_at DESC).
Clients → CDN (media) → API gateway (auth, rate limit, TLS) → stateless app/services behind a load balancer → Redis cache + sharded DB + S3. A queue (Unit 08) sits behind uploads for the media pipeline and behind posts for feed fan-out. Services: Upload/Post, Feed, Image-serving, Notifications, Developer API (Unit 14). Containerized, on Kubernetes, autoscaled (Units 09, 12).
Your turn (spend the most time here): how is the home feed built and served?
Hybrid fan-out. Normal users: on post, a worker fans out the post id into followers' precomputed feed lists in Redis (capped sorted sets) — reads are O(1). Celebrities (followers > ~100k): skip fan-out; at read time merge their recent posts into the follower's precomputed feed. Cache the rendered feed page with a short TTL; protect hot posts from stampedes via coalescing + jitter (Unit 06). Cursor pagination. Source-of-truth posts in the sharded DB + S3; counts denormalized and eventually consistent.
Biggest tradeoff: precomputed (push) feeds for read speed at the cost of write amplification — mitigated by the celebrity hybrid. Failure mode: if Redis loses a feed, rebuild it from the DB (pull) on the fly; degrade to chronological if the ranking service is down (Unit 14). Observability: golden signals per service, alert on feed p99 and queue depth (Unit 13). With more time: ranked feed/ML, search, multi-region active-active.
Tap each you actually did out loud. Aim for all six.
Rotate through these and self-grade each: URL shortener, rate limiter, chat/messaging, ride-sharing, video streaming, notification system, leaderboard. Each reuses the same units — you've now got the whole toolkit. Revisit any unit from the dashboard whenever a tool feels shaky.