Lessons
1 · System Design Foundations
2 · APIs and Communication
3 · Capacity Estimation
4 · Core Building Blocks
5 · Databases
- 12Relational Databases and Data Modeling for System Design
- 13Database Indexes and Query Performance: How to Make Reads Fast
- 14Transactions, Isolation Levels and Concurrency Control: Preventing Race Conditions
- 15Database Replication: Primary-Replica, Read Replicas, Lag and Failover
- 16Database Sharding and Partitioning: How It Works and When You Need It
- 17SQL vs NoSQL: Data Models and How to Choose the Right Database
6 · Distributed Systems
- 18Why Distributed Systems Are Hard: Partial Failure, Timeouts and Clocks
- 19CAP Theorem and Consistency Models Explained Without the Myths
- 20Idempotency, Retries and Message Delivery Guarantees
- 21Distributed Transactions: Two-Phase Commit, the Outbox Pattern and Sagas
- 22Distributed Locks, Leases, Leader Election and Consensus
7 · Reliability and Operations
8 · Architecture and Security
9 · Interview Method and Foundation Case Studies
10 · Real-World Case Studies
- 33Design a Notification System: Email, SMS and Push at Scale
- 34Design a Chat System Like a Messaging App
- 35Design a News Feed: Fan-Out, Ranking and the Celebrity Problem
- 36Design Search Autocomplete (Typeahead)
- 37Design a Distributed Job Scheduler
- 38Design a Ticket Booking System Without Overselling
- 39Design a Payment System: Idempotency, Ledgers and Reconciliation
11 · Large-Scale Case Studies
- 40Design a Video Streaming Platform: Upload, Transcoding and Adaptive Streaming
- 41Design a Ride-Hailing System: Location, Matching and Real-Time Updates
- 42Design a Food Delivery Platform: Orders, Restaurants and Delivery Partners
- 43Design an E-Commerce System: Catalog, Cart, Checkout, Inventory and Flash Sales
- 44Design a Web Search Engine: Crawling, Inverted Indexes and Ranking
12 · Interview Readiness
Lesson 40 · Large-Scale Case Studies
Design a Video Streaming Platform: Upload, Transcoding and Adaptive Streaming
Design an on-demand video platform: resumable uploads straight to object storage, a parallel transcoding pipeline that splits videos into chunks and renditions, adaptive bitrate streaming with HLS-style segments and manifests, CDN delivery at terabits per second, storage tiering, view counting, failures, content safety and the metrics that matter to viewers.
For
SDE-2 candidates preparing for large-scale media design questions, and engineers working on upload, processing or delivery pipelines.
Level
Before you start
Read CDNs and Object Storage (article 10), Message Queues (article 11), Estimating Storage and Bandwidth (article 07) and Design a Distributed Job Scheduler (article 37). Sagas from article 21 help with the processing workflow.
On this page
Key takeaways
- Video platforms are dominated by bytes: storage grows by petabytes and viewing needs terabits per second, so object storage and CDNs carry the design.
- Upload directly to object storage with resumable multipart uploads, then process asynchronously.
- Transcode in parallel by splitting each video into chunks and renditions, orchestrated as a workflow with idempotent, retryable steps.
- Adaptive bitrate streaming serves short segments at several qualities, so the player can switch as network conditions change; immutable segments cache extremely well.
- Viewer experience is measured by start-up time and rebuffering, not server latency, and view counts are an eventually consistent analytics pipeline.
When you press play on a video, the first frame appears within a second or two, and if your train enters a tunnel the picture gets blurrier for a moment instead of freezing. Behind that are two large systems. One takes a creator's 4 GB upload over a patchy connection, turns it into dozens of versions at different qualities, and stores them. The other delivers small pieces of those versions to millions of viewers at once, from servers close to each of them.
An exercise in article 06 estimated that 50 million daily viewers watching 30 minutes each at 5 Mbps need roughly 10 terabits per second at peak; with a more realistic mix of qualities, this article arrives at about 8. This case study designs the platform that makes that possible. It is the first Level 3 case study: several pipelines, enormous byte volumes, and asynchronous processing everywhere.
What you will learn
#- How to estimate a byte-dominated system: ingest, storage, compute and egress.
- Resumable uploads of very large files.
- A parallel transcoding pipeline and how to orchestrate it reliably.
- Adaptive bitrate streaming: renditions, segments and manifests.
- CDN delivery, caching rules, access control and multi-CDN.
- Storage tiering, view counting, failures and observability.
1. The problem
#Build a video-on-demand platform where creators upload videos and viewers watch them on phones, laptops and TVs over networks ranging from fast fibre to weak mobile data. Videos must start quickly and keep playing smoothly as bandwidth changes.
2. Clarify the requirements
#Question | Assumed answer | Impact |
|---|---|---|
On-demand or live? | On-demand; live streaming is an extension | Batch processing is acceptable |
Upload sizes? | Up to 10 GB, typically a few hundred MB | Multipart, resumable upload |
Output qualities? | 240p to 1080p (4K for some creators later) | Rendition ladder |
Devices? | Mobile, web, smart TVs | Standard streaming formats |
How soon after upload must a video be watchable? | Most videos within minutes; long videos within an hour | Parallel transcoding |
Global audience? | Mostly India, some worldwide | CDN with good regional presence |
Private or paid videos? | Some private and unlisted videos; paid content and DRM out of scope | Signed URLs |
Comments, likes, recommendations? | Out of scope (other services) | Metadata only |
View counts? | Shown publicly, can lag by minutes | Analytics pipeline |
Functional requirements: upload a video; process it into streamable formats with thumbnails; stream with adaptive quality; show metadata and view counts; delete videos.
Non-functional requirements
Quality | Target |
|---|---|
Playback start time | p90 under 2 seconds on a typical mobile connection |
Smoothness | Rebuffering under 1% of watch time |
Processing time | 95% of videos under 20 minutes long are ready within 15 minutes of upload |
Durability | An uploaded original is never lost |
Availability | Playback 99.95%; uploads 99.9% |
3. Assumptions and scale estimation
#All figures below are assumptions for this exercise.
Uploads and ingest
200,000 uploads/day; average raw size 300 MBIngest: 60 TB/day -> about 700 MB/s, about 5.6 Gbps on averageStored renditions (a ladder of 5 qualities with assumed bitrates):
240p 0.4 Mbps + 360p 0.8 + 480p 1.5 + 720p 3 + 1080p 6 = 11.7 Mbps for all renditions togetherAverage video 5 minutes = 300 s -> 11.7 x 300 / 8 = about 440 MB of renditions per video200,000 videos/day x 440 MB = about 88 TB/day of renditions; about 32 PB/yearPlus originals: 60 TB/day, about 22 PB/year (kept for re-processing; can move to archive storage)Viewing and egress
50 million DAU x 30 minutes/day; average delivered bitrate 2.5 Mbps (mix of qualities)Concurrent viewers on average = 50M x 30 / 1,440 minutes = about 1.04 millionAverage egress = 1.04M x 2.5 Mbps = about 2.6 Tbps; peak (factor 3) about 7.8 TbpsTranscoding compute (an assumption to replace with measurements for your codec settings): producing the whole ladder takes about 10 CPU-minutes per minute of video.
200,000 videos x 5 minutes x 10 CPU-minutes = 10 million CPU-minutes/day/ 1,440 minutes = about 6,900 CPU cores busy on average (more at peak upload times)Conclusions: egress (terabits per second) and storage (tens of petabytes a year) dwarf everything else. The design must push delivery to CDNs, store bytes in object storage with tiering, and run transcoding as a large, elastic, parallel batch system. The metadata database is small by comparison.
4. API design
#POST /v1/videos{ "title": "Monsoon trek to Kudremukh", "size_bytes": 4200000000, "content_type": "video/mp4", "visibility": "public" }201 { "video_id": "v_9a1", "upload": { "upload_id": "...", "part_size": 104857600, "part_urls_endpoint": "/v1/videos/v_9a1/upload-parts" } }POST /v1/videos/{videoId}/upload-parts {"part_numbers": [1,2,3]} -> presigned URLs for those partsPOST /v1/videos/{videoId}/complete {"parts": [...]} -> 202 { "status": "processing" }GET /v1/videos/{videoId}200 { "status": "ready", "duration_s": 312, "thumbnail_url": "...", "playback_url": "https://cdn.example/v_9a1/master.m3u8?sig=..." , "views": 18234 }POST /v1/playback-events (batched from players: start, quality switches, rebuffering, progress)DELETE /v1/videos/{videoId}The upload API hands out presigned URLs per part, so bytes go straight to object storage (article 10); our servers handle only metadata. Playback URLs point to the CDN and are signed for private or unlisted videos.
5. Data model
#videos (video_id PK, owner_id, title, description, visibility, status (uploading, processing, ready, failed, blocked, deleted), duration_s, original_key, renditions (list of quality and path), created_at, published_at) index (owner_id, created_at DESC)processing_jobs (video_id, step, chunk, rendition, status, attempts, output_key, updated_at) PK (video_id, step, chunk, rendition) -- one row per unit of workview_counts (video_id, day, views) -- aggregated, eventually consistentObject storage layout (immutable objects, deterministic keys): raw/v_9a1/original.mp4 work/v_9a1/chunks/00017.mp4 hls/v_9a1/1080p/segment_00017.ts (or fragmented MP4 segments) hls/v_9a1/1080p/index.m3u8 hls/v_9a1/master.m3u8 thumbs/v_9a1/0003.jpgDeterministic object keys make processing steps idempotent: rerunning a step overwrites the same objects with identical content.
6. Baseline architecture
#Creator --upload--> App server (stores the file on disk) --> serves the MP4 file to viewersA single file served from our servers: uploads tie up app servers, a 4 GB upload restarts from zero on any network drop, viewers on slow networks buffer constantly because there is only one quality, viewers far away wait on long round trips, and our servers would need to push terabits per second.
7. What breaks first?
#- Uploads: large files through app servers, no resume.
- One quality for everyone: 1080p stalls on mobile data; 240p looks terrible on a TV.
- Transcoding time: encoding a long video sequentially into five qualities can take longer than the video itself.
- Egress: terabits per second cannot come from our origin.
- Storage growth: tens of petabytes a year.
- Popular videos: a viral video concentrates traffic on a few objects.
8. Scaling the design
#Resumable upload
#The client splits the file into parts (here 100 MB), uploads them in parallel to object storage with presigned URLs, retries only failed parts, and can resume after the app restarts by asking which parts are already present. Amazon's S3 documentation describes multipart upload for exactly this: parts uploaded independently and in any order, failed parts retransmitted without affecting others, pause and resume, and a recommendation to use it for objects of 100 MB or more (Multipart upload). On completion, the object store assembles the original, and an object-created event (or the client's complete call) starts processing.
The processing pipeline
#Upload complete -> 1. Validate: real container and codec, duration, size limits; malware scan -> 2. Probe: resolution, frame rate, audio tracks -> 3. Split into chunks of about 10 seconds, at keyframe boundaries -> 4. Transcode: for each chunk x each rendition, one task (fan-out: a 5-minute video = 30 chunks x 5 renditions = 150 parallel tasks) -> 5. Assemble and package: per rendition, segment and write a media playlist; then the master playlist -> 6. Thumbnails and preview sprites -> 7. Moderation and copyright checks (automated, with human review for flagged items) -> 8. Publish: write the master playlist last, set status = ready, emit VideoReady- Orchestration: a workflow engine or a saga orchestrator (article 21) tracks each video's steps in
processing_jobs, schedules tasks onto queues, and retries failures. Each task is small (one chunk, one rendition), so failures cost little to redo. - Workers are a large, autoscaled fleet of competing consumers (article 11; Competing Consumers), scaled on queue depth, often on cheaper interruptible capacity since tasks are short and retryable.
- Parallelism turns a 2-hour video's transcoding from hours into minutes, limited mainly by how many workers you can give it.
- Priorities: short videos and verified creators can go to faster queues; very long uploads to a separate queue so they do not starve everyone else.
- Idempotency: tasks write to deterministic keys; the orchestrator marks a task done only after its output exists; duplicates simply overwrite identical objects.
- Re-processing: keeping originals lets you re-encode the library when a better codec arrives, as a background batch job.
Adaptive bitrate streaming
#Instead of one file, each rendition is cut into segments a few seconds long, and playlists (manifests) describe them:
master.m3u8 lists the renditions and their bandwidths 240p/index.m3u8 -> segment_00001.ts, segment_00002.ts, ... 480p/index.m3u8 -> ... 1080p/index.m3u8 -> ...The player downloads the master playlist, starts with a modest rendition (for a fast start), measures download speed as it fetches segments, and switches rendition at segment boundaries: up when bandwidth allows, down before its buffer runs out. HTTP Live Streaming (HLS), specified in RFC 8216, defines this playlist and segment format (RFC 8216, HTTP Live Streaming); MPEG-DASH is a widely used alternative built on the same idea. Because segments are ordinary files fetched over HTTP, any CDN can serve them.
Choices worth stating:
Choice | Trade-off |
|---|---|
Segment length (for example 2 versus 6 seconds) | Shorter segments adapt faster and start sooner; more requests and slightly less efficient encoding |
Number of renditions | More rungs give smoother adaptation; more storage and transcoding |
Codecs | Newer codecs cut bitrate for the same quality; more encoding compute and device-support constraints |
Delivery through CDNs
#- Segments and VOD playlists are immutable: give them long cache lifetimes (
Cache-Control: public, max-age=31536000, immutable). A popular video's segments are served almost entirely from CDN edges after the first viewers in each area. A CDN such as CloudFront delivers content from edge locations close to viewers (What is Amazon CloudFront?). - An origin shield (a mid-tier cache between edges and object storage) collapses requests from many edges, so a viral video does not create thousands of origin fetches.
- Pre-warm edges for scheduled premieres.
- Changes use new paths (re-processed videos get a new version prefix) rather than invalidation; CloudFront's documentation recommends versioned file names over invalidation for frequently updated files (Invalidating files). Invalidation is kept for takedowns.
- Multi-CDN: at terabits per second, many platforms use more than one CDN and steer traffic by cost and performance per region; a CDN outage then degrades, rather than stops, playback.
With 95% of bytes served from cache, origin egress at the 7.8 Tbps peak is about 390 Gbps, still large, which is why the shield and long TTLs matter so much.
Storage tiering
#Viewing is highly skewed: most views go to recent and popular videos. Lifecycle rules move originals to archive storage after processing, and renditions of rarely watched videos to cheaper infrequent-access tiers (keeping the most-used renditions hot). Some platforms even delete the highest renditions of videos nobody watches and regenerate them on demand from the original.
View counting
#Players send batched playback events (start, progress, quality changes, rebuffering) to an ingestion endpoint, which writes them to an event stream (article 11; Kafka-style streams keep events ordered per partition and retain them for replay (Introduction to Kafka)). Stream processors:
- count a view when a session passes a threshold (for example 30 seconds or a percentage of the video), deduplicating by session and filtering obvious bots;
- aggregate counts per video per minute and update
view_counts, which the API serves from cache; - compute quality-of-experience metrics (start time, rebuffering) for monitoring.
The evolved architecture
#UPLOAD PATHCreator app --metadata--> Upload API --> metadata DB (status uploading) --parts (presigned, parallel, resumable)--> Object storage (raw/)Object created --> Workflow orchestrator --> queues --> transcoding workers (autoscaled) --> packaging --> object storage (hls/) --> moderation --> publish (status ready, VideoReady event)PLAYBACK PATHViewer app --> Metadata API (cached) --> signed playback URL --> CDN edges (multi-CDN) --> origin shield --> object storage (hls/)Player events --> ingestion --> stream --> view counts, QoE metrics9. Failure scenarios and reliability
#Failure | Effect | Response |
|---|---|---|
Upload interrupted | Partial upload | Resume by retrying missing parts; lifecycle rule cleans abandoned uploads |
Transcoding worker dies mid-task | Task unfinished | Queue redelivers; deterministic outputs make reruns safe |
A video fails repeatedly (corrupt file) | Poison task | Limited retries, then dead letter; video marked |
Orchestrator restarts | Workflow paused | State in |
CDN outage in a region | Playback errors | Steer to another CDN; players retry other hosts |
Viral video | Origin requests surge | Origin shield, long TTLs, pre-warming |
Corrupted segment in storage | Playback glitch | Checksums verified at packaging; re-package from the original |
Object storage regional outage | Playback and uploads fail in that region | Cross-region replication of popular renditions and originals per requirements (article 24) |
10. Consistency
#- Publishing is atomic from the viewer's point of view: the master playlist is written last and the status switches to
readyonly after every rendition exists, so no viewer ever loads a playlist that references missing segments. - Metadata, search and counts are eventually consistent (seconds to minutes).
- Deletion: metadata status changes immediately (the video stops being playable through the API, and signed URLs stop being issued), CDN caches are invalidated for takedowns, and objects are deleted asynchronously.
- Creators see their own video's processing status immediately (read from the primary).
11. Security
#- Upload safety: validate formats by content, not file extension; scan for malware; enforce size and duration limits; rate-limit uploads per account.
- Content safety: automated moderation and copyright matching before publishing, human review for flagged videos, and fast takedown.
- Access control: private and unlisted videos use short-lived signed URLs or signed cookies at the CDN, and the bucket accepts requests only from the CDN.
- Hotlinking and scraping: signed URLs with expiry; rate limits on metadata APIs.
- Paid content (extension): digital rights management encrypts segments and controls key delivery; it adds licence servers and device constraints.
12. Observability
#Signal | Why |
|---|---|
Video start time (time to first frame), p50 and p90, by region and network | The viewer's first impression |
Rebuffering ratio and average delivered bitrate | Smoothness and quality |
Playback error rate by CDN, region and device | Delivery health; multi-CDN steering |
CDN hit ratio and origin egress | Cost and origin protection |
Upload success rate and resume rate | Creator experience |
Processing time (upload complete to ready), p95; queue depth per stage | Pipeline health |
Transcoding failures and dead letters | Bad inputs or bugs |
View-count pipeline lag | Freshness of counts |
The most important observation: the metrics that matter here are measured on the client (start time, rebuffering), because server latency says little about the viewer's experience.
13. Trade-offs
#Decision | Chosen | Alternative | Why |
|---|---|---|---|
Upload | Direct multipart to object storage | Through app servers | Scales, resumable, keeps servers out of the byte path |
Transcoding | Chunked and parallel | Whole-file sequential | Minutes instead of hours; small retryable tasks |
Renditions | Full ladder for new videos; regenerate rare ones on demand | Everything always | Storage cost versus readiness |
Streaming | Adaptive bitrate with short segments | Single progressive file | Smooth playback on changing networks |
Delivery | Multi-CDN with origin shield | Single CDN or own servers | Terabit egress, resilience, cost leverage |
Storage | Tiered by age and popularity | Single hot tier | Tens of petabytes per year |
14. The final interview answer
#"This is a byte-dominated system: about 60 TB of uploads a day, around 90 TB of renditions a day, and roughly 8 Tbps of viewing traffic at peak.
Creators upload directly to object storage with resumable multipart uploads; the API only handles metadata. Completion starts a workflow: validate and scan, split the video into 10-second chunks at keyframes, transcode every chunk into five renditions in parallel on an autoscaled worker fleet, package HLS segments and playlists, generate thumbnails, run moderation, and publish by writing the master playlist last and marking the video ready. Every task writes to deterministic keys, so retries are safe.
Viewers get a signed playback URL; the player fetches the master playlist from a CDN and adapts quality segment by segment. Segments are immutable and cached with very long lifetimes behind an origin shield, across more than one CDN, so the origin sees a few percent of bytes. Storage is tiered by age and popularity. Playback events stream into an analytics pipeline that counts views after a threshold and measures start time and rebuffering, which are the metrics we actually optimise."
Exercises
#Exercise 1
Storage for a 4K tier
#You add a 4K rendition at 16 Mbps for 20% of new videos. Using the assumptions above (200,000 videos a day, 5 minutes each), how much extra storage per day and per year does it add?
Exercise 2: How long for a 2-hour video?
#A 2-hour video is split into 10-second chunks and transcoded into 5 renditions. Each chunk-rendition task takes about 60 seconds of wall time on one worker (an assumption). How many tasks are there, how long would it take on one worker, and how long with 300 workers available for this video? What else limits the total time?
Exercise 3: Segment length
#A product manager asks for 1-second segments "so playback starts faster". What are the costs, and what would you recommend?
Exercise 4: Honest view counts
#Design view counting that resists inflation by bots, while keeping counts within a few minutes of real time. What counts as a view, and where do you deduplicate?
Show solutionHide solution
Per 4K video: 16 Mbps x 300 s / 8 = 600 MBVideos per day with 4K: 20% of 200,000 = 40,000Extra per day: 40,000 x 600 MB = 24 TB; per year: about 8.8 PBA 4K rung for only a fifth of videos adds about 27% to the daily rendition storage (24 TB on top of 88 TB). Good candidates for tiering: generate 4K only for videos from creators who upload in 4K and whose viewers have 4K devices, and move 4K renditions of unpopular videos to cold storage or delete and regenerate them on demand.
Exercise 2
Show solutionHide solution
Chunks: 7,200 s / 10 s = 720Tasks: 720 x 5 renditions = 3,600One worker: 3,600 x 60 s = 216,000 s = 60 hours300 workers: 3,600 / 300 = 12 rounds x 60 s = about 12 minutesOther limits: downloading the original and uploading outputs (network bandwidth to object storage); the splitting and packaging steps (partly sequential, though packaging can run per rendition in parallel); queue scheduling overhead; fairness (one huge video should not grab all workers, so per-video concurrency caps apply, which lengthens its time but protects others); and moderation, which may need human review.
Exercise 3
Show solutionHide solution
Costs of 1-second segments: many more requests (6 times as many as 6-second segments: more load on CDNs and origin, more per-request overhead, worse on high-latency mobile links); less efficient compression (keyframes at every segment start increase bitrate for the same quality); more objects and playlist entries.
Start-up time depends mostly on fetching the playlist, the first segment at a modest rendition and buffering a few seconds. Better levers: start at a lower rendition and switch up; a short first segment or a small "fast start" rendition; preloading the playlist when the user hovers or scrolls to the video; and good CDN hit ratios. A segment length of 2 to 4 seconds is a common compromise; measure start time and rebuffering with experiments before deciding.
Exercise 4
Show solutionHide solution
- Definition: a view is a playback session that plays at least N seconds (for example 30) or a percentage of a short video, from a session that passes basic validity checks (signed playback token, real progress events, plausible timing).
- Deduplication: count at most one view per (user or device, video) per time window (for example 30 minutes), in the stream processor, using keyed state with expiry.
- Bot filtering: discard sessions without valid tokens, with impossible behaviour (thousands of starts from one IP, no progress events, headless patterns), and from known bad sources; weight or hold back views from new accounts and suspicious traffic for later validation.
- Freshness: the stream processor emits per-minute aggregates; the API serves a cached count. Optionally show a provisional count quickly and adjust it after a delayed fraud review (some platforms visibly freeze or adjust counts while validating).
- Audit: keep raw events for a period so counts can be recomputed if the rules change.
Where to go next
#- Next: Design a Ride-Hailing System: Location, Matching and Real-Time Updates, where the challenge is millions of tiny, constantly changing records instead of huge immutable files.
- Related: CDNs and Object Storage and the job scheduler (article 37).
Sources & further reading
- Technology
- Software Engineering
- #case study
- #CDN
- #distributed systems
- #object storage
- #roadmap
- #scalability
- #system design
- #system design interview
Connected lessons
Linked from 1 guide
Other pages in the library that point here.
Keep reading
More in Technology →Guide · Technology
Start Here: Your Roadmap from Zero to Job-Ready DSA
Guide · Technology
Heaps and Priority Queues
Guide · Career
A LinkedIn Profile That Gets Recruiter Messages

