Skip to main content

Design YouTube (Video Streaming Platform)

Design Instagram already established the shape of this problem for images: separate metadata from large media, process uploads asynchronously, deliver through a CDN. Video is the same shape at a much larger scale, plus two genuinely new hard problems images don't have: a single video needs to be transcoded into many different formats and qualities, and playback needs to adapt continuously to a viewer's changing network conditions rather than just loading once. Following the framework from How to Answer a System Design Interview Question.

1. Requirements​

Functional:

  • Creators upload video; viewers stream it back smoothly across a wide range of devices and network conditions.
  • Playback should adapt automatically to available bandwidth rather than stalling or requiring a manual quality choice.

Non-functional:

  • Upload processing can tolerate real delay (minutes, for a long video) — the same tolerant-upload, latency-sensitive-playback split already established for Instagram.
  • Storage and egress bandwidth needs are enormous — video is orders of magnitude larger per item than a photo, and every playback re-streams that size repeatedly.
  • Playback start time and smoothness (no stalling/buffering) are the metrics viewers actually feel.

Scale estimate: assume 500 hours of video uploaded per minute, and each video re-encoded into roughly 6 quality renditions (240p through 4K) — meaning total stored bytes are several times the original upload volume, before counting that popular videos are streamed millions of times each.

2. API Design​

POST /videos multipart upload returns: { video_id, status: processing }
GET /videos/{video_id}/manifest returns: { renditions: [{ resolution, segment_urls }] }

The manifest, not a single video file URL, is what a player actually requests — it's the index the deep dive below explains.

3. Data Model​

videos (metadata — relational database)
video_id VARCHAR PRIMARY KEY
uploader_id VARCHAR
status ENUM(processing, ready, failed)

renditions (object storage, referenced by metadata)
video_id VARCHAR
resolution ENUM(240p, 360p, 480p, 720p, 1080p, 4k)
segment_urls LIST<VARCHAR> -- short chunks, not one giant file

Storing each rendition as many small segments rather than one large file per resolution is deliberate, and it's what the adaptive streaming deep dive below depends on entirely.

4. High-Level Design​

System Design Lab

Same Event-Driven Architecture shape as Instagram's upload pipeline — upload finishes and publishes an event; transcoding happens asynchronously and independently — but transcoding one video is itself a large, parallelizable job, which is the first deep dive below. Playback is served entirely through a CDN, the same edge-caching justification as Instagram's photo delivery, just for a far larger and more bandwidth-hungry payload.

5. Deep Dive: parallelizing transcoding across workers​

Transcoding a two-hour video into six resolutions on one worker, sequentially, could take far longer than viewers (or the platform's storage costs while a video sits unprocessed) can tolerate. The standard fix is splitting the source video into independent chunks (a few seconds each) and transcoding chunks in parallel across many workers, then reassembling the segments — the same Concurrency vs. Parallelism idea applied concretely: real parallel hardware doing genuinely simultaneous work on independent pieces of one job, coordinated through the same message queue-based work distribution already covered generally in that lesson. A failed chunk can be retried independently without redoing the whole video, which also makes this pipeline naturally resilient to a single worker crashing partway through.

6. Deep Dive: adaptive bitrate streaming​

This is the genuinely new problem video introduces that a static image never has: network conditions change during playback, and a video that started smoothly can hit a slow patch of network minutes in. The fix is exactly why videos are stored as many small segments per resolution rather than one file per resolution:

System Design Lab

The player continuously measures its own recent download speed and, before requesting each next segment, chooses whichever resolution it can fetch comfortably within that segment's playback duration — switching to a lower resolution the instant bandwidth drops rather than continuing to request a resolution that will stall. Because every resolution is pre-segmented into matching short chunks, the player can switch resolutions between segments seamlessly, without needing to re-buffer the whole file in a new quality.

7. Tradeoffs​

Generating all six resolutions upfront, for every uploaded video, means paying transcoding cost and storage for renditions that may rarely be requested (a video watched only in 480p on mobile still gets a 4K rendition stored). The alternative — transcoding a resolution only the first time it's actually requested — trades that upfront cost for a slower first playback at an untranscoded resolution, and real added complexity in caching and serving partially-transcoded content.

Segment length from the adaptive-streaming deep dive carries its own tension, worth naming explicitly: shorter segments let the player react to a bandwidth drop almost immediately, since it's never committed to more than a couple seconds of a resolution before its next chance to downshift — but more, smaller segments mean more CDN requests overall and slightly worse compression efficiency per segment. Longer segments compress better and mean fewer requests, but a bandwidth drop mid-segment can't be reacted to until that whole segment finishes downloading, which is exactly the stall this design exists to avoid. Real platforms land in the middle — a few seconds per segment — precisely because either extreme reintroduces the problem the other one solves.

Transcode all resolutions upfront vs. on-demand: pros and cons​

Transcode upfront

  • Every resolution is instantly available the moment a viewer requests it
  • No extra latency or complexity on the playback path itself
  • Simpler operationally — one finite job per upload, not an ongoing one

Transcode on demand

  • First request for a rarely-used resolution pays a real transcoding delay
  • Adds real complexity to the serving path for handling in-progress transcodes
  • Needs a caching layer for completed on-demand renditions to avoid re-transcoding repeatedly

Further Reading​

Share this lesson

Saved locally in your browser — visible in the sidebar as you go.