Books Deep-Read · System Design Interview Vol 1 · Ch 14
System Design Interview Vol 1 · Ch 14 · Alex Xu · 2020
You tap a video, it starts within a second or two, and it keeps going when you walk from wifi onto mobile data. This chapter asks: what do you actually have to build to do that for millions of people? The answer is a little surprising — the hard part is not the playing. It is getting the film ready and getting it close to you.
The file you carefully uploaded is never watched by anyone. Once the platform receives it, it makes a dozen other versions from it: a small one for phones, a big one for TVs, a tiny one for when your signal is bad, plus a cover image and an audio track. Viewers always watch one of those copies. The original just sits in a warehouse as the master.
Because viewers' devices and networks are wildly far apart. The same film — what a TV on home fibre can swallow is more than ten times what a phone on the subway can. Ship only one version and you lose either way: ship the big one and half your audience stalls; ship the small one and the other half calls it blurry. So every portion size has to be prepared in advance, and the player picks. But preparing them is brutally expensive: one hour of HD, encoded start to finish on one machine, can take hours.
① A central kitchen that plates several portion sizes. The film comes in, gets prepped, then is cooked into a whole set of differently sized outputs. That step is called transcoding.
② Cut it into pieces so a hundred cooks work at once. Video has natural cut points — every few seconds there is a "complete picture" you can start playing from. So the hour-long film is cut into hundreds of few-second pieces, hundreds of machines cook them at the same time, and the results are stitched back in order. Total time no longer depends on how long the film is; it depends on the slowest single piece.
③ Ship the popular ones to the corner shop near you. The finished versions live in a central warehouse, but you may be half a world away from it. So the platform pushes only the hottest ones out to "corner shops" a few dozen kilometres from you — that's a CDN. You are served from the corner shop, which is why it's fast.
Every trade-off here is about money. Push every version of every film to every corner shop on earth and the bill explodes — the single biggest cost of a platform like this is the bandwidth of sending video out. So the real approach is tiering: popular titles live in the corner shop, obscure ones are fetched from the central warehouse, and obscure ones may not even get the full set of portion sizes made ahead of time — they get cooked when somebody finally asks.
The honest price: the video you just uploaded takes minutes, sometimes longer, before a high-definition version exists — it is queued on that pipeline.
The two genuinely hard things about a video platform are turning one source file into a whole set of differently sized outputs (by cutting it into pieces and working in parallel) and getting those outputs near the viewer (by shipping only the popular ones). Playback itself is the most settled part of the business.
Want the mechanisms, the numbers and the diagrams? → Switch to the deep read
You think designing YouTube is hard because of playback. In fact playback is the most settled, most standardised part of the field (CDN plus adaptive bitrate — copy the recipe). What you actually have to design is two things: a transcoding pipeline that parallelises, tolerates faults and can be changed, and a way to push down a distribution bill that runs six figures a day. The value of this chapter is not "how YouTube works"; it is the demonstration that when one stage's cost grows linearly with the business, every architectural decision ends up being dragged around by that cost.
.mp4/.mkv are the "box" — how audio and video tracks sit inside one file. H.264/VP9/AV1 are the compression algorithms that decide how the picture is squeezed. They combine freely.Mbps. Higher is sharper and hungrier.This is late in Part II of Vol 1 (the case studies), and it is the volume's largest-data, most nakedly cost-driven problem. It pairs with Ch 15, "Design Google Drive": both handle large files, but Drive cares about sync and conflict while YouTube cares about processing and distribution. In the real world it maps to YouTube, Netflix, TikTok — and to any platform with an "after upload, something must happen" stage: photo clouds, podcast hosts, screen recorders.
Put the numbers up first or the discussion is hot air. The book's setup: 5 million daily active users, 5 videos watched per user per day, so playback runs at about 5,000,000 × 5 ÷ 86,400 ≈ 289 requests per second. That number is small — read it alone and you would think this problem is easy. The frightening ones are the other two:
300 MB. That's 500,000 uploads/day = 150 TB of new source footage every day, and it only ever goes in.$0.02/GB, 25 million views × 0.3 GB × $0.02 ≈ $150,000 per day, over $50M a year — and that is at only 5M DAU.Three pain points follow. One: the source cannot be played directly. Uncompressed 1080p at 30 fps and 3 bytes per pixel is roughly 186 MB/s, about 670 GB per hour; even an already-compressed source is a disaster for a phone on 4G, and device format support is all over the map. Two: transcoding is a CPU monster. One machine encoding a one-hour 4K title can run for hours — make users wait all afternoon and the product is dead. Three: distribution cost scales linearly with views, the one line item that gets more expensive the more successful you are. Every design move in the chapter answers one of these three.
The first thing to internalise: a video's byte stream and its metadata (title, description, thumbnail and so on) travel completely different paths. Mixing them is the classic beginner error.
The upload path: the client asks an API server for a pre-signed URL, then PUTs the source file's parts straight into object storage — those hundreds of megabytes never touch an application server. Landing the source triggers the transcoding pipeline, which writes a full ladder of outputs into another bucket and pre-warms popular content to the CDN. When the pipeline finishes it drops an event on a completion queue; a completion handler writes back to the metadata database, and only then does the video move from "processing" to "playable". Metadata travels its own light path: client → API server → metadata DB and cache.
The playback path is much shorter: the player hits the nearest CDN edge, fetches the manifest, then pulls segments rung by rung according to measured bandwidth. In the normal case a playback request never reaches your backend at all.
Transcoding answers three problems at once: the source is huge, devices support different formats, and the viewer's bandwidth keeps moving. The method is to encode the source into several rungs along a bitrate ladder — commonly five or six (240p/360p/480p/720p/1080p) plus audio, thumbnails and subtitles. In other words one source balloons into a dozen-odd artefacts, and the full set typically costs 1.5–2× the storage of the top rung alone.
With the manifest in hand, the player re-measures actual throughput every few seconds and picks the rung for the next segment. That is exactly why every rung must be cut into time-aligned segments (2–10 seconds under HLS/DASH): only aligned boundaries let you switch rungs without a visible jump. When bandwidth drops the viewer sees "it went soft for a moment" instead of a spinner — that is the whole value of adaptive bitrate.
This is the design most worth taking away. The book says outright that the model is borrowed from Facebook's streaming video engine: do not write transcoding as one script that runs top to bottom; write it as a directed acyclic graph. The source is split into video, audio and metadata tracks; the video track then carries tasks — inspection, encoding per rung, thumbnail extraction, watermarking — and everything converges into packaging and manifest generation. The dependencies between tasks are the graph's edges.
Why bother? Because requirements never stop arriving. Today add an AV1 rung, tomorrow pick cover frames with a model, next week legal wants a watermark on a content class. As a script, each of those means editing the main flow and re-running everything; as a graph it means hanging one more node and re-running the affected subgraph. That is what "evolvability" looks like inside a concrete system.
Around the graph sits the scheduling skeleton: a preprocessor splits GOPs and generates the graph from the video's characteristics; a DAG scheduler cuts the graph into stages by dependency; a resource manager keeps task and idle-worker queues and hands work out; workers execute, with intermediates in temporary storage. The payoff is that each layer scales on its own — encoding slow, add workers.
Everything above exists to make this one thing possible. Every few seconds a video has an independently decodable keyframe; a GOP cut there can be encoded on its own. So the hour-long title becomes hundreds of 5–10 second chunks, hundreds of machines encode simultaneously, and the results are stitched back by index.
End-to-end time goes from "proportional to running time" to "≈ the slowest chunk plus the stitch" — an order-of-magnitude change, and the dividing line between "watchable in minutes" and "wait all afternoon". The same incision reaches back into upload: the client cuts on GOP boundaries before sending, a failure re-sends only one chunk, and upload and transcoding overlap. Old client that can't chunk? The server splits the whole file itself, forfeiting the overlap.
Back to that $150,000 a day. The book's savings list rests entirely on one observation — the long tail: a few videos take the overwhelming majority of views. Hence: push only popular videos to the CDN and serve the tail from your own high-capacity storage servers; don't pre-encode the full ladder for obscure videos, encode when someone actually asks; distribute by region, since a video popular in one country needs no worldwide footprint; and once volume justifies it, build your own CDN by putting hardware directly into ISP facilities.
Two more items are not about money but belong here. Security: uploads use pre-signed URLs (valid for minutes, for one key only); on playback, layer protection by content value — DRM, AES encryption, visible watermark, each cheaper and weaker than the last. Error handling: separate recoverable errors (a chunk failed to encode → retry a few times, then fail the job) from non-recoverable ones (the format simply isn't supported → stop immediately with a clear error), so retry logic never hides genuinely bad input.
Table 1 · Which path do the upload bytes take?
| Option | How it works | Upside | Price |
|---|---|---|---|
| Pre-signed URL, direct | Client gets a single-use address and PUTs parts straight into object storage | Zero byte traffic through the API tier; bandwidth pressure lands on the storage service | A leaked URL is a leaked upload grant — needs short expiry and a single-key scope; validation must be deferred |
| Relayed via API servers | Client POSTs to the app server, which writes to storage | Auth, validation and tagging can happen at upload time | A 300 MB body pins a connection and memory for a long time; the API tier must scale on upload bandwidth and will fall over first |
| Client-chunked parallel upload | Cut into 5–10 MB parts on GOP boundaries, sent concurrently | A failure re-sends one part; upload overlaps transcoding, fastest end to end | Heavy client complexity; older clients can't, so the server needs a fallback splitting path |
Table 2 · Granularity of transcoding parallelism
| Cut | End-to-end time | Fits | Price |
|---|---|---|---|
| Whole file, serial | Proportional to running time | Very short clips, offline backfill | An hour of 4K takes hours — unusable for an interactive product |
| GOP chunks, parallel across time | ≈ slowest chunk + stitch | The on-demand main path | Needs a scheduler, temp storage and stitch alignment; chunks too small and scheduling overhead outweighs the win |
| Parallel across rungs only | Still proportional to running time, but all rungs at once | Live — future frames don't exist yet, so you cannot cut across time | Parallelism caps at the number of rungs; latency has to come from shorter GOPs and shallower buffers instead |
Table 3 · Four ways to push down the CDN bill (the book's savings list)
| Lever | How | Saves | Price |
|---|---|---|---|
| Hot / cold tiering | Only popular videos enter the CDN; the tail is served from your own high-capacity storage servers | The set you must distribute shrinks by an order of magnitude — big cut in traffic fees | Noticeably higher startup latency for tail content |
| Encode on demand | Obscure videos get no pre-built ladder; encode when someone watches | Storage and transcoding compute | The first viewer waits; a sudden hit gets a rough period |
| Regional distribution | Place copies only where the audience actually is | Cross-region origin pulls and redundant copies | Guess wrong and you pull across an ocean, adding hundreds of milliseconds to startup |
| Build your own CDN | Put purpose-built caching hardware inside ISP facilities (Netflix Open Connect is exactly this) | Lowest long-run unit cost of delivery | Upfront capex plus a permanent operations team; below a certain volume it simply doesn't pay |
This problem is the parent of every "upload → process → distribute" system: swap in audio and it's a podcast host, images and it's a photo cloud, short clips and it's TikTok, files and it's the next chapter's Google Drive. What an interview tests here is never "do you know HLS" — it is whether you treat cost as a design constraint on your own initiative. The candidate who can quote the daily CDN bill and the one who only draws boxes differ exactly there.
5800 kbps to 2000 kbps with no visible quality loss — the chapter's fixed ladder is a starting point; real systems recompute it from content complexity. Netflix TechBlog, “Per-Title Encode Optimization”, 2015 ↗① The claim: video platforms are hard not because of playback (CDN + ABR is settled) but because of the transcoding pipeline and the distribution bill.
② Numbers first: at 5M DAU playback is only about 289 req/s, but you take in 150 TB of new source a day and spend roughly $150,000 a day on CDN — cost is the binding constraint.
③ Split the paths: hundreds of megabytes go straight to object storage via a pre-signed URL; only metadata crosses the API tier, and playback closes at the CDN edge.
④ Transcoding turns one source into a dozen artefacts along a bitrate ladder, costing about 1.5–2× the top rung in storage.
⑤ Express it as a DAG, not a script: a new format is one more node — evolvability made concrete.
⑥ The decisive incision is GOP-chunked parallelism: end-to-end time goes from ∝ running time to ≈ slowest chunk + stitch, and upload overlaps encoding.
⑦ All four savings levers rest on the long tail: hot/cold tiering, encode-on-demand, regional distribution, and your own CDN once volume justifies it.
⑧ Split errors into recoverable and non-recoverable; layer security as pre-signed URLs plus DRM / encryption / watermark. Live is a different question — tighter latency, shorter GOPs, no parallelism across time.