System Design Case Study
Photo / video social feed
Film a short reel, tap share, then scroll home while friends' stories appear at the top. It feels instant. Behind that moment is cheap , an async , and a feed that must stay fast for hundreds of millions of daily users.
This design is media-heavy and read-heavy. Store photos and videos efficiently, process them asynchronously, then make feeds, stories, and explore feel immediate, even when a posts.
Upload → feed journey
Raw media lands; post metadata is recorded.
Compress, resize, multi-bitrate variants.
Push to normal followers; celebrities wait for read.
Feed hydrates; CDN delivers the heavy bytes.
Try it: media upload then feed read
Uploads land in blob storage; the feed path reads metadata plus CDN URLs, not original bytes from the app servers.
- Client
- Upload API
- Object store
- Feed service
- CDN
- Uploads
- 0
- Feed reads
- 0
- Mode
- upload
- Path hop
- 0
Write path
async0 uploads accepted.
Read path
CDN0 feed reads; heavy bytes stay off app servers.
Consistency
eventualA newly uploaded post may lag briefly on distant feed caches.
Upload media or open a feed read to separate the write path from CDN-backed reads.
What actually happens
Opening the app loads a personalized home feed and a . Feed reads dominate traffic: roughly a 100:1 read:write ratio. So the design precomputes timelines in an and ships media through a .
Publishing is not "write once to every follower." Normal accounts use write fan-out into follower caches. skip full push and merge on read. Meanwhile the builds image sizes and video bitrates in the background.
Stories expire after 24 hours via . Explore is a separate discovery path: candidate generation plus lightweight , not the same graph walk as the following feed. Expiration is a read-time rule as well as a cleanup task. Store an expiry timestamp on the story, filter it from trays and media access when that time passes, and remove old storage asynchronously. A delayed TTL worker must not keep an expired story visible. Retained audit or recovery copies need separate access rules so storage retention does not accidentally extend product visibility.
How to choose the hard paths
1. Who is posting? Normal graphs can absorb write fan-out. Huge follower counts need read-path merge. That is the heart of .
2. Must the user wait? Feed and story tray need low latency. Transcodes and explore candidates can be asynchronous with placeholders or stale-safe caches.
3. What fails gracefully? Ranking down → chronological cache. Variants lagging → lower-resolution assets. Never make an unrelated feed read wait on moderation or transcode queues.
Simple rule of thumb
Precompute for the common case, special-case celebrities, and put every media byte behind object storage + CDN. Keep privacy checks (block, mute, private accounts) on hydration, not only at publish time.
In simple terms: make uploads durable quickly, make feeds feel instant, and never let one viral author melt the write path.
Case-study upgrade
Photo and Video Feed Math
A media social feed combines normal feed fan-out with expensive media storage, processing, delivery, and short-lived stories.
Assumptions and formulas
- Daily active users: 500M. Feed refreshes/user/day: 20. Media upload: 700 TB/day raw.
- Stories expire after 24 hours but remain hot while active.
- Feed cache stores ids; media variants and thumbnails are served through CDN edge caches.
Concrete math
- Feed reads: 500M x 20/day = 10B/day = 115.7K QPS average; peak can reach 350K to 1M QPS.
- Media upload: 200 TB/day photos + 500 TB/day video = 700 TB/day raw; variants and replicas can make physical storage 2x to 5x.
- Five-year raw storage: 700 TB/day x 365 x 5 = about 1.28 EB before variants and replication.
- Stories: 100M users x 2 stories/day x 2 MB = 400 TB active 24-hour hot story data before variants.
- Feed cache: 500M users x 800 post ids x 8 bytes = 3.2 TB raw; with overhead plan 10 to 50 TB.
Design decisions forced by numbers
- Media processing must be async; do not publish broken or missing variants.
- Use story TTL stores and tray caches separate from durable post feeds.
- Precompute candidates for explore-like surfaces and rerank only a bounded set online.
Scaling to millions
- At 1M users: object storage, async processors, and a simple following feed are enough.
- At 10M users: add CDN-backed variants, hybrid fan-out, story TTL storage, and search index.
- At 100M+ users: add regional media placement, hot story trays, celebrity replication, and degraded chronological feed.
Readable flow
Interview follow-ups to expect
- Does media delivery cost dominate the system?
- How are stories removed after TTL without leaving cache ghosts?
- How do deletes and privacy changes propagate to feed candidates?
Operational readiness checklist
After the math, explain how this capacity plan is measured, protected, launched, and evolved.
Observability
- Attach each capacity estimate to a dashboard metric: p99 latency, queue age, cache hit rate, shard skew, error rate, and freshness lag.
- Alert on rate-of-change and saturation, not only hard failures; backlogs and hot keys usually warn before an outage.
Security and abuse
- Budget for auth checks, rate limits, quota isolation, audit logging, privacy filters, and abuse-review side paths.
- Separate trusted internal events from user-controlled input so retries and backfills cannot bypass policy checks.
Degraded modes
- Define the fallback when a dependency is slow: stale cache, partial results, read-only mode, delayed async work, or admission control.
- Protect the invariant first; reduce freshness, personalization, or analytics quality before risking duplicate or corrupt state.
Testing and rollout
- Test average, peak, and hot-object traffic; include retry storms, cold caches, lagging workers, and regional dependency loss.
- Use canaries, shadow reads, dual-write validation, feature flags, and explicit rollback criteria for risky path changes.
Rollout, backfill, and runbooks
- Make migrations and backfills idempotent, resumable, rate-limited, and visible through progress and error metrics.
- Write the runbook before launch: owner, dashboards, paging thresholds, mitigation switches, replay steps, and repair commands.
10x evolution
- For photo and video feed math, state which number forces the next move: cache memory, shard count, write amplification, queue lag, egress, or failover reserve.
- Add the next layer only when the metric forces it: sharding, regional reads, async replay, hot-key isolation, or stricter backpressure.
Scope you should nail down
Product surface
- Photo/video posts with captions, hashtags, location
- Stories with 24h TTL; reels as short vertical video
- Personalized news feed from followed accounts
- Follow/unfollow, likes, comments, DMs, search
- discovery beyond the follow graph
Scale targets
- ~2B users, ~500M DAU (order-of-magnitude interview numbers)
- Feed latency under ~200ms p99; story tray often tighter
- Resumable media upload with progress
- High availability (~99.99%) and celebrity-safe fan-out
Capacity picture
Media storage
Traffic
- Read:write ~100:1: feed views dominate
- 500M DAU × 20 refreshes/day ≈ 10B feed reads/day (~115K/sec average; peaks much higher)
- CDN delivery bandwidth is often ~10× storage write bandwidth
Hardening the media feed
Capacity formulas and SLOs
500M DAU × 20 refreshes/day = 10B feed reads/day ≈ 115K QPS average, 350K–1M QPS peak. Feed p99 under 200ms; story tray p99 under 100ms; normal media processing age under a few minutes.
Metrics and degraded modes
Track CDN hit rate, candidate freshness, ranking p99, story tray cache hit rate, transcode backlog, and moderation queue age. Ranking fails → cached chronological feed; variants lag → placeholders or lower-resolution assets.
Security, privacy, and abuse
Recheck block, mute, deletion, and private-account visibility during hydration. Rate-limit follows, likes, comments, and DMs; scan media asynchronously; quarantine suspicious uploads without breaking unrelated reads.
Rollout and 10× growth
Replay publish events into a shadow feed, canary ranking changes, backfill story tray indexes after TTL policy changes, and test regional CDN loss. At 10×, add regional media placement, hot story tray replicas, and precomputed explore candidates by segment.
Hard-part drill: viral celebrity story + post
Skip full push fan-out, replicate media variants at the edge, cache the story tray for followers, and merge celebrity candidates on feed read before privacy filtering and lightweight ranking.
APIs worth sketching
- POST /posts: uploadPost(user_id, media, caption, type: photo|video|reel)
- GET /feed: getFeed(user_id, cursor, limit): ranked feed
- GET /stories: getStories(user_id): friends' active stories
- POST /stories: uploadStory(user_id, media): 24h TTL
- GET /search: searchUsers / searchHashtags / searchPlaces
- POST /posts/{id}/like: likePost(user_id, post_id)
- POST /posts/{id}/comments: commentPost(user_id, post_id, text)
- GET /explore: getExploreFeed(user_id, cursor)
Core data model
Users
Posts
Followers
Likes
Comments
Stories
High-level architecture
News feed generation
Use fan-out on write when copying one post ID into the timelines of likely readers is affordable. For an author with a huge audience, retain the post in an author stream and merge it during follower reads instead. The threshold depends on posting rate, active audience, and read frequency; one million followers is only an illustrative tuning point. Deduplicate candidates from both paths during migrations or retries.
Ranking first retrieves eligible candidates and then orders them using bounded-cost signals such as recency, relationship strength, and predicted interest. Candidate generation determines what the ranker can ever show, so improving the model cannot recover a missing post that never entered the set. Separate feature freshness from query latency and keep a chronological fallback when model or feature dependencies fail.
Cache shape: A per-user timeline can keep a bounded set of post IDs with time or rank scores. Trimming to an illustrative 800 entries bounds memory but means older history requires another source. When scores change between page requests, numeric offsets can repeat or skip entries; use a cursor tied to a defined ranking version or snapshot, then recheck visibility during hydration.
Media processing pipeline
Upload → (raw) → stream/queue → compress + resize → multiple resolutions / HLS-DASH bitrates → → update DB URLs. Images often use ~4 sizes; video uses multiple bitrates. Keep raw uploads, processing jobs, and published media variants as separate records. A worker writes immutable outputs and validates them before making a variant available in post metadata. Duplicate job delivery should find or rebuild the same version safely. Failure to create one optional high-resolution variant can degrade quality, while missing the minimum required variant keeps the upload in an explicit processing or failed state.
Stories and explore
24h stories
Hot storage ( + with ). Lighter processing than durable posts. Preload tray media for friends on app open.
Explore retrieves candidates beyond the viewer’s follow graph using topic, content, and engagement signals, then applies safety and visibility filters before final ranking. Retrieving 1,000 and returning 50 is an example budget, not a required architecture. Precomputed candidate sets reduce live cost but can become stale or overly repetitive, so measure coverage, freshness, and diversity alongside ranking latency.
Storage choices and sharding
- Relational: users, relationships, comments: ACID and structured queries
- : feed and activity streams
- : feed, hot posts, sessions, sorted timelines
- + : media variants
- Shard posts, feed, and followers by user_id (consistent hashing)
- User timeline: single shard lookup
- Home feed: precomputed cache sharded by user_id
- Media keys: hash(media_id) for even object distribution
Bottlenecks to call out
Celebrity fan-out
Mitigation: fan-out on read for >1M followers.
Media upload spike
A viral upload creates several different loads: one-time media processing, replicated media downloads, timeline candidate work, and engagement events. Encoding the same video repeatedly for every viewer wastes compute; the CDN should reuse immutable variants. Scale or isolate each bottleneck independently, and coalesce simultaneous misses so a popular uncached segment does not send every edge request to the origin.
Storage growth
~1.2 EB in 5 years: tier old content to cold storage.
Explore ML latency
Precompute candidate sets; rank live with a lightweight model.
Takeaway
Photo/video social feed design is dominated by media volume and personalized fan-out. Balance celebrity write amplification, async processing, story TTL cleanup, and discoverability ranking without losing delivery speed.
Review the design
Hybrid fan-out for feed: precompute for normal users, read path for celebrities.
Media pipeline: upload → object storage → compress → multiple image sizes / multi-bitrate video → CDN.
Stories: 24h TTL, hot storage, pre-loaded for friends.
Explore: ML recommendation, content graph, engagement signals.
Stack: relational (structured), wide-column (feed), in-memory cache, object storage + CDN, search index.
Shard by user_id with consistent hashing.
Compare a starting answer with a more complete design
A starting answer
Explain users, follows, posts, media storage, feed cache, likes, comments, stories, and CDN-backed media delivery.
Developing the reasoning
Deep dive media processing states, hybrid feed fan-out, story TTL cleanup, explore ranking, feature freshness, celebrity accounts, and graceful media degradation.
Deeper walkthrough
photo/video social feed deeper walkthrough
photo/video social feed is a media-heavy social graph system. The upload path, feed path, story path, and explore path should be designed as related but separate workflows.
Requirement refinements
Clarify posts, reels, stories, DMs, explore, comments, likes, search, privacy, and content moderation scope.
State that feed reads should be fast, while media processing and explore ranking can be asynchronous.
API design details
Use separate media upload and post publish APIs so a post can show processing or failed_media states.
Use cursor pagination for feed and story tray reads, with visibility checks during hydration.
Data model and storage
Store post metadata separately from media variants and processing jobs.
Use TTL metadata for stories and keep engagement events in streams for ranking features.
Scaling strategy
Use hybrid fan-out for following feed and Content Delivery Network (CDN)-backed media delivery for every image and video variant.
Replicate hot celebrity content and cache story trays because short-lived content can still be very hot.
Reliability, recovery, and operations
If ranking fails, return a safe chronological or cached feed; if media processing fails, keep the post in a visible retryable state.
Monitor feed p99, media processing age, Content Delivery Network (CDN) hit rate, story tray latency, and ranking feature freshness.
Deepening reference
Media Feed: realistic production notes
Beginner mental model: A media feed combines media storage, feed fan-out, stories TTL, social graph, and discovery ranking.
Production scope: The photo/video path must handle uploads and processing, while the feed path must hydrate media and rank candidates quickly. Stories, reels, DMs, and explore are separate workloads.
Choose what the first version must guarantee
Start by deciding which media feed capabilities are essential. Describe the main read and write operations before choosing infrastructure. For each operation, identify the stored records it uses and the condition that makes its result correct. A fast response is useful only if it satisfies that condition.
Next, separate work the user must wait for from work that can finish later. Estimate requests per second, storage growth, and the busiest object or customer. Use those estimates to choose one bottleneck to investigate. The calculations below are example workloads with stated assumptions; they are not measured limits of a particular product.
Concrete capacity calculations
Uploads: 100M daily users, 10 percent posting once/day, average processed media 5 MB gives 50 TB/day of new feed media before replicas.
Feed reads: if 100M users open feed 15 times/day, that is 1.5B feed sessions/day, about 17K/sec average and 85K/sec at 5x peak.
Story reads: 50M story authors with 200 average viewers creates 10B story views/day. Natural TTL keeps storage bounded, but read caches are hot.
Feed cache: 500 candidate IDs per active user at 16 bytes each is 8 KB/user. For 100M active users, candidate lists are about 800 GB before overhead.
Media bandwidth: 1.5B sessions/day with 20 MB viewed per session is 30 PB/day delivered, so edge cache hit rate dominates cost and latency.
Scaling to millions of users
Separate media upload/processing from feed delivery. Feed should reference ready media variants, not wait on raw processing.
Use hybrid fan-out for following feed and read-time ranking for high-follower authors or discovery candidates.
Partition stories by author_id with TTL metadata; filter expired stories at read time as a safety net.
Hydrate feed candidates in batches and verify visibility before returning cached media references.
When ranking signals lag, serve recent following content and stale-but-valid recommendations.
Sequence and data-flow diagram
Walk this path after the high-level design so it is clear what is synchronous, what is asynchronous, and where the system can degrade safely.
Read the diagram definition
sequenceDiagram
participant User
participant M as Media API
participant O as Object storage
participant P as Processing workers
participant F as Feed service
participant C as Candidate cache
User->>M: Upload media post
M->>O: Store raw object
M->>P: Queue processing
P->>O: Store variants
P->>F: Publish ready post
F->>C: Add candidates to feeds
User->>F: Open feed
F-->>User: Ranked media candidatesCore flow to walk through
Upload post: raw media upload, async processing, metadata write, fan-out candidate event.
Open feed: fetch feed candidates, rank, hydrate media URLs, return paginated response.
Story: write ephemeral object and metadata with TTL, update story tray for followers.
Production readiness
Media Feed: ship, operate, and evolve
Now examine the same request flow during failures and deployments. Tie each operational control to the user behavior it protects.
Observability
Track media feed p95/p99 latency, error rate, saturation, and user-visible freshness separately for read, write, and async paths.
Alert on leading indicators such as queue age, hot-key skew, cache miss storms, reconciliation mismatches, and error-budget burn.
Security and abuse
Enforce authentication, authorization, rate limits, input validation, audit trails, and privacy checks at the service boundary.
Treat abuse controls as a first-class path: throttling, quota isolation, moderation hooks, revocation, and safe handling of sensitive data.
Degraded modes
Name what still works if cache, search, ranking, stream processing, object storage, or a regional dependency is slow.
Prefer stale-but-safe reads, partial results, async retry, admission control, and feature disablement over corrupting core state.
Testing and rollout
Load test average, peak, and hot-object traffic; add failure-injection for retries, timeouts, backlog growth, and dependency outages.
Ship with canaries, shadow reads or dual writes when useful, rollback switches, schema compatibility checks, and replay validation.
Runbooks
Document dashboards, paging thresholds, owner actions, rollback steps, data repair commands, and customer-impact language.
Keep backfills and replays idempotent, resumable, rate-limited, and observable so repair work does not create a second incident.
10x evolution
Say which metric forces the next architecture change: shard count, cache footprint, write amplification, queue lag, p99 latency, or regional failover reserve.
Evolve one bottleneck at a time: partition by access pattern, isolate hot tenants, regionalize reads, add replayable async pipelines, then harden multi-region behavior.
Hard parts worth deepening
Media processing is async; users need visible processing states.
Feed ranking needs fresh engagement signals but should not block on them.
Stories have high write/read volume with natural TTL cleanup.
Explore is a recommendation problem separate from following feed.
Failure modes and recovery
Media processing backlog; show pending post and prioritize small previews.
Celebrity post creates fan-out spike; use hybrid fan-out and merge on read.
CDN degradation; serve lower resolution or stale cached media.
Story TTL cleanup lags; filter expired stories at read time as backup.
Signals to monitor
Feed p99 and story-read latency describe different read paths and should have separate targets. Media-processing age shows whether newly uploaded content is waiting for transformations before it can appear.
Track CDN hit rate to see how much media traffic reaches origin. Ranking-feature freshness measures how old the model inputs are; a fast ranking response can still be poor if its features are stale.
| Choice | Best when | Cost |
|---|---|---|
| Precompute feed | Low feed latency matters. | Write amplification. |
| Rank on read | Personalization freshness matters. | Higher read CPU and latency. |
| Multiple media resolutions | Devices and networks vary widely. | Extra transcode and storage cost. |
Try this scenario
Walk through posting a reel and explain which parts are synchronous versus asynchronous.
Primary sources
- Instagram Engineering: Sharding & IDs: feed identity and shards.
- Nishtala et al.: Scaling Memcache at Facebook: feed cache patterns.
- Amazon S3: Objects: photo/video blob storage.
Practice and further reading
Use these exercises to connect the lesson to a design decision. State your assumptions, trace what happens to one request, and explain the rule that must remain true even during a failure. That rule is the design's correctness invariant.
Focus for this lesson: Combine resumable media upload, processing, moderation, privacy, feed/story ranking, CDN lifecycle, deletion, and fan-out economics.
Explain the decision
When should a media post become visible?
Read the reasoning
Only after authoritative metadata commits and required variants/moderation state are ready; publication is a versioned state transition.
Apply it to a production scenario
A user makes an account private while cached feed candidates exist. What protects privacy?
Read one approach
Hydration performs current visibility checks, invalidates caches asynchronously, and monitors privacy/deletion propagation lag.
Work through the numbers
Fifty million uploads/day average 3 MB and generate 2x derivative bytes. Estimate daily logical ingestion.
Read the worked calculation
About 450 TB/day total original plus derivatives, before replicas, failed uploads, and metadata.
Reason through a failure
What must deletion guarantee?
Read the recovery reasoning
All discoverability and authorization paths deny access promptly, while asynchronous CDN/object cleanup is tracked to a bounded completion SLO.
Sources and further study
Continue with Design Ride Matching.