Design YouTube (Video Streaming) — the walkthrough in full
A written version of the interactive walkthrough above — the same steps, decisions and trade-offs, laid out for reading, reference and search.
The big idea
How does YouTube stream to a billion screens?
A creator uploads one enormous file. Billions of viewers — on fibre, on 3G, on a TV — must each watch it starting in under a second, in the best quality their connection can handle, without buffering.
The trick is that you never serve "the video." You serve a metadata lookup, then a flood of tiny pre-encoded segments from a server near the viewer. Almost everything here is about turning one raw upload into something a CDN can spray across the planet.
How to read this: Each step opens with a real design decision — you make the call before I show you what ships. Watch the diagram grow into a streaming platform, and at the end kill the CDN to see what origin alone is up against. Hit Begin.
Step 1 · The skeleton
Split the bytes from the facts
A video is two very different things: a few hundred bytes of metadata (title, owner, status) and gigabytes of raw media. Storing them the same way is a mistake.
Design decision: A video is a few hundred bytes of metadata plus gigabytes of raw media. How do you store them?
The call: Metadata in a DB, raw bytes in a Blob Store (S3-like). — Tiny structured facts go in a queryable database; huge write-once media goes in cheap object storage. Watch requests read metadata first, then fetch bytes — splitting them is the foundation.
Keep facts in a Metadata DB and bytes in a Blob Store (object storage like S3). The Upload Service streams the raw file into the blob store and writes a small row in the metadata DB. Watch requests read metadata first, then go get bytes.
Metadata vs blobs: Structured, queryable, tiny data belongs in a database. Huge, opaque, write-once files belong in cheap object storage. Mixing them wastes money and makes both slow — splitting them is the foundation.
Step 2 · The pipeline
One file becomes many
The raw upload is useless for streaming: it’s one giant file in one codec at one resolution. A phone on 3G and a 4K TV need wildly different versions.
Design decision: The raw upload is one giant file in one codec. A 3G phone and a 4K TV need different versions. How do you produce them?
The call: Async: queue an encode job; workers build an ABR ladder of segments. — The upload service drops a job on a queue; a transcoder fleet re-encodes into 240p–4K, each chopped into small ~2–10s segments written back to blob, then marks the video ready. The player switches quality mid-stream from the precomputed ladder (HLS/DASH).
Make encoding asynchronous. The Upload Service drops a job on a queue; a fleet of Transcoder workers re-encode the file into an ABR ladder — 240p, 480p, 720p, 1080p, 4K — each chopped into small (~2–10s) segments, then written back to the blob store. When done, they mark the video ready in metadata.
Adaptive bitrate (ABR): Encoding many qualities up front lets the player switch resolution mid-stream as bandwidth changes — that’s why a video drops to fuzzy and recovers instead of freezing. Standards like HLS and DASH describe the ladder in a manifest.
Step 3 · The hot path
Serving the watch
Views dwarf uploads by orders of magnitude, and viewers are everywhere on Earth. Streaming every segment from one origin datacenter would be slow and ruinously expensive.
Design decision: Views dwarf uploads and viewers are everywhere. Streaming every segment from one origin would be slow and ruinous. Fix?
The call: Put a CDN in front; serve immutable segments from edges. — The player pulls the manifest then segments from the nearest edge; the first regional viewer warms the cache, everyone after gets bytes from down the street. Immutable segments cache perfectly — the CDN offloads 95%+ of traffic. The CDN IS the read-scaling strategy.
Put a CDN in front of the blob store. To watch, the player fetches the manifest (from metadata) then pulls segments from the nearest CDN edge. The first viewer in a region warms the cache; everyone after gets bytes from down the street. Origin traffic stays tiny.
Why a CDN wins: Video segments are immutable and re-watched constantly — the ideal cache target. Pushing bytes to edges close to users cuts latency and offloads ~95%+ of traffic from your origin. The CDN is the read-scaling strategy.
Step 4 · A mountain of bytes
Storing exabytes affordably
Every upload now becomes 5–6 renditions, each in many segments — multiplying storage. Hundreds of hours are uploaded every minute. You cannot keep it all hot.
Design decision: Every upload becomes 5–6 renditions in many segments, and 500 hours arrive every minute. How do you store exabytes affordably?
The call: Tiered storage: replicate popular content, push the long tail to cold storage. — A tiny fraction of videos drive most views — keep those replicated and ready; let the millions of near-zero-view uploads sit in cheap cold tiers, accepting a slower first byte if someone finally watches them.
Lean on tiered blob storage: replicate popular content across regions for fast origin pulls, and push the long tail of rarely-watched videos to cheaper cold storage. Generate thumbnails and previews once, store them as blobs too, and serve them from the CDN.
Hot vs cold: A tiny fraction of videos drive most views. Keep those replicated and ready; let the millions of near-zero-view uploads sit in cheap cold tiers, accepting a slower first byte if someone finally watches them.
Step 5 · Don’t fall over
Scale the control plane
The CDN handles the bytes, but metadata reads, search, and upload coordination still hit your services — and one big server is a single point of failure.
Design decision: The CDN handles bytes, but metadata reads, search and upload coordination still hit your services, and one server is a SPOF. How do you scale them?
The call: Load balancer + stateless service copies; split read vs write planes. — Run many stateless instances behind a load balancer with a hot-metadata cache, and separate upload, watch-metadata and search so each scales — and fails — independently, keeping the 99% read path resilient when writes surge.
Put a load balancer in front and run many stateless copies of each service. Add a read cache for hot metadata. Split upload, watch-metadata, and search into services that scale — and fail — independently, so a spike in uploads never takes down playback.
Separate read and write planes: Watching (read) and uploading/encoding (write) have totally different shapes and traffic. Isolating them lets each scale on its own and keeps the 99% read path resilient when writes surge.
Step 6 · Count the views
Views, watch time & recs
Owners and the recommender want view counts, watch time, and quality stats. Writing a row on every play — and incrementing a counter on a viral video — would hammer the database.
Design decision: Owners want view counts and watch time, but a DB write per play (and a counter bump on a viral video) would hammer it. How?
The call: Emit lightweight watch events to a stream; aggregate asynchronously. — Plays emit events into an analytics pipeline; counts aggregate in the background (approximated for hot videos), and recommendations train on the same stream — never on the playback critical path. If analytics lags, playback is unaffected.
Make it asynchronous. The player emits lightweight watch events that flow into an analytics pipeline; counts are aggregated in the background and approximated for hot videos. Recommendations train on this same event stream — never on the playback critical path.
Decouple with events: A fast producer (plays) and slow consumers (analytics, ML) run at different speeds via a stream. If analytics lags, playback is unaffected; events wait in the log and get processed later.
Step 7 · The sharp edges
Uploads, copyright & live
Real life intrudes: uploads fail halfway on flaky connections, pirated content appears, and some events must stream live with seconds of delay, not after a full encode.
Use resumable, chunked uploads so a dropped connection retries only the missing chunk. Run a content-matching system (fingerprinting) to flag copyrighted material. For live, encode segments on the fly and publish the manifest continuously — same ABR + CDN idea, just streaming as it happens.
Design for the unhappy path: Flaky upload → resume the chunk. Pirated upload → fingerprint and flag. Live event → encode-as-you-go. Thinking through what happens when things go wrong is what turns a demo into YouTube.
You did it
You just designed YouTube.
- S — p
- A — s
- A — d
- A —
- T — i
- A — s
- R — e