On this page
Description
Video is where ordinary web-app habits break down. Files are gigabytes rather than kilobytes, processing a single upload takes minutes to hours, and delivering it to millions of viewers adds up to terabits a second. "Design YouTube" or "design Netflix" is a favourite interview question because each of those three facts needs its own answer.
In this lesson:
- Why the simple version fails, and the numbers that decide the design.
- Uploading huge files reliably, in resumable parts.
- The transcoding pipeline: chunks, workers and a bitrate ladder.
- Adaptive bitrate streaming (HLS and DASH).
- Delivery through a CDN, metadata, and storage tiers.
The first version, and why it breaks
A startup adds video to its app the simple way. POST /upload sends the file to an app server, which runs ffmpeg to make an MP4 and saves it. GET /video/42 streams that MP4 back. It works perfectly in the demo.
Then a creator uploads a two-hour 4K recording over hotel Wi-Fi. The upload dies at 80% and has to start again from zero. When it finally arrives, the conversion ties up a request thread for forty minutes. And viewers on phones keep stalling, because the only version that exists is one big 20 Mbps file.
Video breaks the habits of a normal web app. Files are gigabytes, processing takes minutes to hours, and delivery is measured in terabits a second. Each of those needs its own answer.
The numbers
- 1 million uploads a day, averaging 5 minutes long and about 500 MB raw.
- 200 million viewers a day, with up to 20 million watching at the same time.
- At about 4 Mbps per viewer, peak delivery is 20 million × 4 Mbps = 80 Tbps.
- Playback should start within 2 seconds, and adjust to the viewer's connection instead of stalling.
No fleet of app servers sends 80 Tbps. That number alone tells you the video must come from a CDN, a network of caches close to viewers.
Uploading
Don't send gigabytes through your app servers. Instead:
- The API hands the app pre-signed URLs: temporary permissions to upload straight to the object store (such as Amazon S3).
- The app uploads in parts (say 64 MB each). Each part can be retried on its own, so a dropped connection resumes from the last finished part instead of starting over. This is called a multipart, resumable upload.
- When every part is up, the app tells the API, which records the video as
PROCESSING.
The transcoding pipeline
Transcoding means converting the video into the formats and sizes viewers need. It's slow and CPU-heavy, so it never runs inside a web request:
- The API puts a transcode job on a queue.
- The video is cut into chunks (say 10 seconds), so hundreds of workers can encode different parts at the same time. A two-hour video then takes minutes instead of hours.
- Each chunk is encoded at several sizes and qualities, called a bitrate ladder: for example 240p at 0.4 Mbps up to 1080p at 6 Mbps, plus 4K for 4K sources.
- The output is cut into segments a few seconds long, with manifests (playlists) that list them, and saved back to the object store.
- When every chunk is done, the video is marked
READY.
Workers crash and jobs get retried, so every step must be safe to repeat: encoding the same chunk twice must produce the same segment file.
Adaptive bitrate streaming
With HLS or DASH (the two standard formats), the player first downloads a manifest that lists every version of the video and its segments. While playing, it keeps measuring how fast segments arrive and how much video it has buffered, and it picks the version for each next segment:
The video gets a bit blurrier for a few seconds instead of freezing. Starting with a low-bitrate first segment also makes playback start quickly.
Delivery
Segments and manifests are ordinary files, so a CDN caches them in locations near viewers, with the object store as the origin it fetches from on a miss.
- Segments never change after they're written (a re-encode gets new paths), so they can be cached for a very long time.
- Manifests for live streams change constantly, so they get short cache times.
- Popular videos end up served almost entirely from the CDN, and the origin barely notices them.
Metadata and storage tiers
Titles, owners, processing status and the list of renditions live in a metadata database, with a cache in front for popular videos. The video bytes live in the object store.
Storage is the other big bill. Keep the versions people watch in standard storage. Move the raw originals, which you keep only in case you need to re-encode, to a cheaper cold storage tier.
Which piece solves what
| Problem | Piece |
|---|---|
| Huge uploads over unreliable networks | Multipart, resumable uploads straight to object storage |
| Slow, CPU-heavy conversion | A job queue and many workers encoding chunks in parallel |
| Viewers on different connections | A bitrate ladder, plus HLS or DASH adaptive streaming |
| 80 Tbps of delivery | A CDN in front of the object store |
| Storage cost | Watched versions in standard storage, originals in cold storage |
Common mistakes
- Uploading through app servers. Gigabytes tie up your servers and fail on bad networks.
- Transcoding inside the request. A forty-minute HTTP request is an outage waiting to happen.
- One version of the video. Phones on slow networks stall, and everyone else downloads more than they need.
- Serving video from your own servers. Terabits a second need a CDN.
- Non-repeatable workers. A retried job that produces different files breaks caching and wastes storage.
Check yourself
Try to answer before opening each one - recalling beats re-reading.
1. Why split a video into chunks before transcoding?
Show answer
So many workers can encode different parts at the same time, and a long video finishes in minutes instead of hours. A failed chunk is also retried on its own instead of restarting the whole video.
2. What does the player do when the connection slows down halfway through a video?
Show answer
It picks a lower-bitrate version, listed in the manifest, for the next segments. Playback continues at lower quality instead of stalling, and it switches back up when the connection recovers.
3. Why can a CDN cache segments for a very long time?
Show answer
A segment never changes once it's written. A new encode gets a new path, so a cached copy can never go stale.
Key takeaways
- Upload in resumable parts, straight to object storage, with pre-signed URLs.
- Transcode in the background: a queue, chunks, many workers, a bitrate ladder, then mark the video ready.
- Store HLS or DASH segments plus manifests. The player picks the bitrate for each segment.
- Serve through a CDN with the object store as origin. Terabits don't come from app servers.
- Metadata in a database with a cache; video bytes in object storage; originals in cold storage.