Vibe Engines
YouTube

Vibe Engines is free, interactive AI engineering & system design — runs in your browser. Pick a learning path

System Design

Design YouTube

Learn system design by building a video platform like YouTube step by step.

The numbers to beat5–6quality rungs~4sper segmentasyncvia queue

The whole design, in writing

Every step of the build above, written out: the problem each piece solves, the option that was taken and the ones that were not, the numbers, and how it fails in production.

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.

Upload UIPlayer
New in this step: Upload UI, Player. · swipe to pan the diagram

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.

What the new pieces do

Upload UIcreator
A creator uploading a huge raw file. Uploads once and wants it watchable everywhere, in every quality.
Playerviewer
Anyone hitting play. Expects the video to start in under a second and never buffer, on any connection.

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.

App ServerUpload ServiceMetadata DBBlob Store
New in this step: App Server, Upload Service, Metadata DB, Blob Store. · swipe to pan the diagram

A video is a few hundred bytes of metadata plus gigabytes of raw media. How do you store them?

  1. Gigabyte media blobs bloat a database, make queries slow, and waste its expensive indexed storage. Databases are for small structured queryable data, not opaque write-once files.

  2. Object storage is great for the giant media but terrible for the queryable facts (title, owner, status, search) you constantly look up. You need a database for those.

  3. 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.

Why this piece earns its place

Splitting the stores means one upload is now two writes to two systems with no transaction across them, and both orderings fail. Write the row first and a failed blob upload leaves a video the catalog swears exists with nothing to play. Write the bytes first and a failed row leaves gigabytes nobody will ever reference and nobody will ever be billed for. So I make the metadata row the commit point — bytes land in the blob store first, under a key derived from the video id, and the row only becomes real once they are there — and treat status as a state machine the pipeline advances, not a label. Orphaned blobs then become a known, tolerable category: a sweeper walks keys against rows and reclaims whatever the catalog never claimed. The subtler cost is that reading a video is now two hops in two failure domains. The metadata DB falling over does not merely break search, it breaks playback, because the player cannot discover which renditions exist. That is what makes metadata worth caching hard later, on a path the CDN can never help with: the edge caches the bytes, not the row that says which bytes exist.

What the new pieces do

App Serveredge
The front door for uploads and watch requests. Becomes an API Gateway behind a load balancer.
Upload Serviceservice
Accepts the raw upload (resumable, in chunks), stashes it in blob storage, and queues it for processing.
Metadata DBstore
Small structured data: title, description, owner, status, and the manifest of available renditions.
Blob Storestore
Object storage (S3-like) holding the giant raw upload and every encoded segment. The origin behind the CDN.

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.

Transcoderencode ABREncode Jobsqueue
New in this step: Transcoder, Encode Jobs.

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?

  1. Re-encoding per view is enormously expensive and slow — you’d redo the same work for every viewer. Encode once, up front, into all qualities and reuse.

  2. 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).

  3. Creators upload one master file and can’t be expected to produce a full ABR ladder of segmented renditions. Encoding is the platform’s job, done asynchronously off the upload path.

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.

Why this piece earns its place

The rung count is the real knob this step introduces, and it is set against two bills at once. Every rung is another full encode of the whole file and another copy in storage — the 5–6 rungs here are already about 6× the bytes — and you pay both for every upload, including the overwhelming majority nobody finishes watching. Cut rungs to save that and the player’s step-down becomes a cliff: with wide gaps between qualities, a viewer whose bandwidth dips slightly has nothing close to fall to and drops much further than the connection warranted, which the viewer sees as an ugly lurch in sharpness. Pack them too close and the player flips between neighbouring rungs on noise. I would set the ladder from the devices and networks actually in the logs rather than from symmetry, and I would decouple the choice from ingest: encode one middle rung immediately so the video becomes watchable, then let workers fill the rest behind it. The same reasoning kills the automatic top rung — building 4K for a video shot at 720p is pure cost.

  • 5–6quality rungs
  • ~4sper segment
  • asyncvia queue

What the new pieces do

Transcoderworker
Workers that re-encode the raw file into many resolutions and bitrates, split into small streamable segments.
Encode Jobsbus
A job queue decoupling fast uploads from slow encoding. Transcoder workers pull jobs at their own pace.

Back of the envelope

1 upload → 5–6 rungs × segments
~6× storage per video
~2–10s per segment
switchable mid-stream (HLS/DASH)
encode async via queue
slow encoding off the fast upload path

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.

PlayerApp ServerTranscoderCDN EdgeBlob Store
New in this step: CDN Edge. · swipe to pan the diagram

Views dwarf uploads and viewers are everywhere. Streaming every segment from one origin would be slow and ruinous. Fix?

  1. More origin capacity in one place still pays a long round-trip to distant viewers and concentrates bandwidth cost. You need bytes physically close to users.

  2. Pre-downloading gigabytes wastes bandwidth (most of a video is never watched) and delays start. You want to stream small segments on demand from a nearby edge.

  3. 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 this piece earns its place

The line about the first viewer in a region warming the cache quietly assumes viewers arrive one at a time. They do not, in the case that matters most: a large channel publishes, or a premiere starts, and the video is cold at every edge on Earth in the same second. All those edges miss on the same opening segments at once and each goes to origin for them, so peak demand is the exact moment the CDN offloads least — and origin was sized on the promise that it would barely be touched. I would want two defenses. Inside an edge, coalesce concurrent misses for one object so a single request goes upstream and the rest wait on its result. Above the edges, run a shield or mid-tier cache in front of the blob store, so the herd collapses at a regional layer instead of at origin. Anything scheduled gets a third: push the opening segments to edges before the premiere rather than discovering they are missing at start time. None of this touches the steady state, where segments genuinely do cache forever — it protects the minute before they have.

  • 95%+served at edge
  • <1sstart time
  • immutablesegments

What the new pieces do

CDN Edgeedge
Thousands of edge servers near users. Serves the actual video bytes so the origin barely gets touched.

Back of the envelope

95%+ served at the edge
origin barely touched
immutable segments
cache forever, no invalidation
1st regional view warms cache
the rest served locally, <1s start

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.

Upload UIPlayerApp ServerUpload ServiceTranscoderCDN EdgeMetadata DBBlob StoreEncode Jobs
The system as it stands at this step. · swipe to pan the diagram

Every upload becomes 5–6 renditions in many segments, and 500 hours arrive every minute. How do you store exabytes affordably?

  1. 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.

  2. Replicating everything everywhere is ruinously expensive when most videos are barely watched. Match storage cost to popularity — hot content hot, cold content cheap.

  3. Deleting creators’ uploads to save space is unacceptable — they expect permanence. The answer is cheaper cold storage for the long tail, not deletion.

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.

Why this piece earns its place

Tiering bakes in an assumption worth saying out loud: that I know which videos are hot, and I only ever know that in the past tense. A tier is assigned from watch history, so the case that hurts is a years-old video a huge account links today — its first bytes come out of cold storage precisely when the demand arrives, and cold storage charges both a retrieval fee and a wait. The mirror failure is thrash: a video hovering at the boundary gets promoted and demoted over and over, and the transitions cost more than the tier ever saved. So I move the two directions at different speeds — promote on the first sign of traffic, demote only after a long quiet — and I keep the decision per rendition rather than per video, because the lowest rung of everything is small enough to leave hot everywhere. A cold video then starts instantly, if fuzzily, while its higher rungs restore behind it, which converts a cold-storage stall into a quality dip. Thumbnails never go cold at all: the catalog renders them, so they belong with the metadata, not with the tail.

  • 500 hrsuploaded / min
  • 6×storage per video
  • tieredhot + cold

Back of the envelope

500 hrs uploaded / minute
× ~6 renditions = exabytes
hot: replicated + ready
the tiny fraction driving most views
cold: cheap, slower first byte
the long tail nobody watches

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.

Upload UIPlayerAPI GatewayUpload ServiceTranscoderCDN EdgeMetadata DBBlob StoreEncode Jobs
The system as it stands at this step. · swipe to pan the diagram

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?

  1. A bigger box has a ceiling and is still a single point of failure, and it can’t isolate an upload spike from the read-heavy watch path. You need many instances and separation of concerns.

  2. Coupling uploads/encoding (write) with watch-metadata/search (read) means a surge in one takes down the other. Their traffic shapes are totally different — isolate them.

  3. 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.

Why this piece earns its place

Stateless is a property I have to keep, not one I get by writing it on a box, and uploads are where it breaks first. A resumable upload is a conversation: chunks arrive over minutes against a session, and if an instance holds which chunks it has in local memory, the load balancer handing chunk forty to a different copy loses the thread. Sticky routing looks like the cheap fix and simply reinvents the single point of failure, one per session — the instance dies mid-upload and the creator starts the file again. So the session state (which chunks landed, their checksums, the blob key being assembled) lives in a shared store, and any instance can continue any upload. Splitting the planes has a second consequence worth naming: failure becomes partial, and partial failure has to be visible. With uploads down and watch healthy, the studio should say uploads are paused rather than let clients retry into a wall — and the watch path must take no hard dependency on anything in the write plane, or I have built two planes that still die together.

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.

CDN Edgeglobal PoPsView Analyticswatch events
New in this step: View Analytics.

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?

  1. 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.

  2. A synchronous counter bump per play on a viral video is a write hotspot that can melt the DB and adds latency to playback. Counting must be async and off the hot path.

  3. Client-only counts are unverifiable and easily gamed, and still need to reach the server. Emit events to a pipeline that aggregates and validates server-side.

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.

Why this piece earns its place

Moving counting onto a stream gives playback its latency back and hands me a different problem: a pipeline like this delivers at least once, so retries, reconnects and a player that fires again after a network blip all arrive as separate events. Summed naively every count is inflated, and inflated most for exactly the videos people reload. So a play gets an id minted once in the player, and events carry it alongside a position, which makes deduplication possible at aggregation and makes replay safe — the day a consumer bug forces a reprocess, I need to run the log again and land on the same number. That forces the question underneath: what a view is. It cannot be a request, because requests are trivial to manufacture; it has to be a threshold on watch time, decided server-side, and written down before two teams compute it separately and disagree in public. I would also expect a published count to move in both directions after a reprocess, so the owner sees a figure openly marked as still settling rather than one that silently goes down.

What the new pieces do

View Analyticsstore
Aggregates views, watch time and quality switches asynchronously, so counting a view never slows playback.

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.

Upload UIPlayerAPI GatewayUpload ServiceTranscoderCDN EdgeMetadata DBBlob StoreEncode JobsView Analytics
The system as it stands at this step. · swipe to pan the diagram

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.

Why this piece earns its place

Everything before this assumed a video has an end. The pipeline waits for a complete file, encodes the whole ladder, then flips a flag to ready — and a live stream has no complete file and no moment to flip. That is why running the same pipeline faster is not the answer: queue-and-drain has no deadline anywhere in it, and a live encoder is nothing but deadlines. Segments have to be produced continuously and published on time, and when a rung misses its slot the right move is to publish the manifest without that rung rather than hold every viewer back for one quality. The assumption that bends next is immutability. Segments stay immutable and still cache perfectly, but a live manifest changes every few seconds, so it needs a short cache lifetime while the segments it lists keep a long one — two very different caching rules inside one stream. Get that wrong and viewers sit on a stale manifest watching a stream that has already moved on, which looks like the player froze rather than like the cache did.

You did it

You just designed YouTube.

Upload UIPlayerAPI GatewayUpload ServiceTranscoderCDN EdgeMetadata DBBlob StoreEncode JobsView Analytics
The finished design, end to end. · swipe to pan the diagram

Everything you assembled, in order

  • Split tiny metadata (DB) from huge media (blob store).
  • Async transcoding turns one raw file into an ABR ladder of segments.
  • Adaptive bitrate lets the player switch quality without buffering.
  • A CDN serves immutable segments from the edge — 95%+ offload.
  • Tiered hot/cold blob storage keeps exabytes affordable.
  • Async watch events drive view counts and recommendations.
  • Resumable uploads, content-ID, and live streaming for the real world.

Deep cut · 13:40

One reel of film, from a café to a porch.

The interactive build above lays out video streaming step by step. The film follows one video, Noor’s birthday message, as a reel of film: a chunked resumable upload, six sizes cut into four-second strips and converted in parallel, a manifest, a shelf for bytes beside a cabinet for facts, local cinemas near viewers, a player that adapts to one bar of signal, and the herd that arrives when a million people press play together.

  • See the numbers: 500 hours a minute is 30,000 video seconds per second. 10,000,000 viewers at 5 Mbps is 50 Tbps. A 4 s strip at 5 Mbps is 20 Mb, which takes 13.3 s on a 1.5 Mbps line.
  • Strips, not a file: a 1 hour video is 900 four-second pieces times 6 sizes, 5,400 files. Minute 30 is strip 450. With 95 in 100 requests found at a nearby cache, 2,500,000 requests a second become 125,000 at the origin.
  • Take it into the interview: resume an upload at chunk 312, step the picture size on the buffer (360p needs 0.7 Mbps), and collapse 1,000,000 identical requests into 1.

Where an interviewer pokes next

Getting the boxes right is the easy half. These are the questions that separate a candidate who drew the diagram from one who has run the thing. Answer each one out loud before you open it.

  1. How does adaptive bitrate (ABR) decide which quality to play?

    The client decides, per segment. The player measures its recent download throughput and buffer level and picks the highest rung the connection can sustain, stepping down when bandwidth drops and back up when it recovers — which is why video gets fuzzy then sharp instead of freezing. The server just offers the ladder via the HLS/DASH manifest; keeping the decision on the client keeps the serving tier stateless and simple.

  2. How are resumable uploads implemented?

    Chunked upload against an upload session: the client splits the file into chunks uploaded against a session id; the server tracks which chunks it has, so a dropped connection retries only the missing chunks (verified with checksums). Protocols like tus or S3 multipart formalize it. It turns a flaky multi-gigabyte upload from "start over" into "resume where you left off."

  3. How does Content-ID / copyright matching work at scale?

    Each upload is fingerprinted (a robust perceptual hash of audio/video) and matched against a database of reference fingerprints from rights holders. Matches trigger policy — block, monetize, or track — without a human watching every video. It runs asynchronously after upload (off the hot path), the same way transcoding does, because it’s expensive and not needed before processing.

  4. How does live streaming differ from video-on-demand here?

    Same ABR + CDN idea, but encode-as-you-go: segments are produced continuously from the live feed and the manifest updates in real time, so viewers stay a few segments (seconds) behind live. You trade some latency for the same adaptive, cacheable segment delivery. The differences are a continuously-growing manifest, tighter encode latency, and no ability to re-encode the past.

  5. Why is splitting metadata from blobs the foundation of the whole design?

    Because the two have opposite needs and scales. Metadata is tiny, structured, queryable, frequently updated — perfect for an indexed, searchable database. Media is gigabytes, opaque, write-once, read-via-CDN — perfect for cheap object storage. Mixing them makes the database huge and slow and wastes money; splitting lets each use the right tool and scale independently, which transcode, CDN and tiering all build on.

Check yourself — the answers, and why

Eight steps in, these are the calls you should be able to make cold. Pick one, then read why.

  1. Tiny metadata and gigantic media are stored…

    Structured queryable facts in a DB; huge write-once files in cheap object storage.

  2. Transcoding one upload into an ABR ladder is done…

    Encode once into many qualities/segments off the upload path; the player switches among them.

  3. A CDN is ideal here because video segments are…

    Edge-cached immutable segments offload 95%+ of traffic and start playback in <1s.

  4. Exabytes stay affordable via…

    Replicate the hot fraction; push the rarely-watched long tail to cheap cold storage.

  5. View counts are computed…

    Plays emit events; aggregation (and recs) happen off the playback critical path.

How you’d open this design in an interview

Before any boxes: agree what it must do, pin the qualities that shape everything, then build — naming each trade-off as you make it. The walkthrough above is that exact order.

What it must do

Agree on these before drawing a single box.

  • Upload: accept one enormous raw file from a creator (resumable, in chunks).
  • Transcode: turn that file into every quality and small streamable segments.
  • Watch: start playback in under a second and adapt quality to the viewer’s connection.
  • Count views: view counts, watch time and quality stats — plus recommendations.
  • Keep it forever: store every video durably and affordably at exabyte scale.

The qualities that shape everything

Each one names the mechanism that buys it.

The DB isn’t bloated by media
Split tiny structured metadata (title, owner, status) into a queryable DB and the gigabyte bytes into a cheap blob store.
One file plays on 3G and a 4K TV without buffering
Async transcoding builds an ABR ladder of small segments; the player switches resolution mid-stream from a HLS/DASH manifest.
Start in <1s and spare the origin
A CDN serves immutable segments from an edge near the viewer — the first regional view warms the cache and it offloads 95%+ of traffic.
Exabytes stay affordable
Tiered blob storage: replicate the popular fraction across regions, push the rarely-watched long tail to cheaper cold storage.
An upload spike never takes down playback
A load balancer fronts stateless service copies, and read (watch/metadata) is split from write (upload/encode) so each scales and fails on its own.
Counting a view never slows playback
The player emits lightweight watch events onto a stream, aggregated in the background — recommendations train on the same stream, off the hot path.

The trade-offs you say out loud

Senior signal isn’t the boxes — it’s naming what you gave up and why it was the right price.

Metadata in a DB, bytes in a blob store over storing the media in the database

Gigabyte media blobs bloat a database, slow its queries, and waste its expensive indexed storage — while object storage can’t serve the queryable facts you constantly look up. The two have opposite needs; splitting them lets each use the right tool and scale independently.

Encode once, async, into an ABR ladder over transcoding on the fly per view

Re-encoding per viewer redoes the same expensive work every time. Drop an encode job on a queue, build 240p–4K segments once off the upload path, and let the player switch among the precomputed ladder as bandwidth changes.

A CDN of immutable segments over more origin servers in one region

Origin capacity in one place still pays a long round-trip to distant viewers and concentrates bandwidth cost. Immutable, re-watched segments cache perfectly at the edge, cut latency, and offload 95%+ of traffic — the CDN is the read-scaling strategy.

Tiered hot/cold storage over replicating every rendition everywhere

A tiny fraction of videos drive most views, so replicating everything everywhere is ruinous — and deleting creators’ uploads is unacceptable. Keep the hot fraction replicated and ready; let the long tail sit in cheap cold storage with a slower first byte.

The answer, out loud

What a strong answer to “Design YouTube (Video Streaming)” sounds like, first question to last trade-off. It is about 7 minutes of talking; the whiteboard and the interviewer fill the rest of the 45. Read it aloud once, then close the page and give it yourself.

  1. 0–3 min

    Frame the traffic first

    Before I draw anything I want to name the shape of the traffic. One person uploads a file once; enormous numbers of people read it, from everywhere, for years. So this is really a write path and a read path that happen to share a product name, and I would expect to design them apart and let them fail apart. And the storage is permanent — a creator uploads once and expects the video to be there forever — so whatever I decide about cost, I am deciding for the life of the video.

  2. 3–8 min

    What a video actually is

    The first real call is what a video is in my system, and my answer is that it is two very different things. There are a few hundred bytes of facts — title, owner, status, which renditions exist — that I query, sort and search constantly. And there are gigabytes of media I write once and then only ever stream back. Those want opposite storage, so the facts go in a database and the bytes go in object storage. Put the media in the database and I get a huge slow database that still cannot search the media.

    Built in step 1: Split the bytes from the facts
  3. 8–15 min

    One file becomes many

    The raw upload is not watchable, though — it is one codec at one resolution, and a phone on 3G and a 4K television want completely different files. So the upload service stores the file, drops a job on a queue and returns, and a fleet of transcoder workers re-encodes it into a ladder from 240p up to 4K, each rung chopped into segments of a few seconds. When the ladder is written they mark the video ready. I want encoding off the upload path in both directions: the creator should not wait on it, and a slow encode should not back up ingest. And I would never transcode per viewer — that repeats the same expensive work for every single person who presses play.

    Built in step 2: One file becomes many
  4. 15–22 min

    The watch path is the CDN

    Now the read path, which is where the scale actually is. The player asks metadata for the manifest, then pulls segments from the nearest CDN edge. I would say plainly that the CDN is the read design, not an optimisation bolted on top of it. Segments never change, so they cache about as well as anything can — no invalidation, and the same bytes serve everyone nearby. The first viewer in a region pays for the origin pull and everybody after them gets the bytes from down the street, which is what buys a start time under a second. The CDN absorbs 95 percent or more of the traffic, and that is most of my bandwidth bill too.

    Built in step 3: Serving the watch
  5. 22–28 min

    Paying for the ladder

    Then I would own what the ladder did to my storage. Every upload became five or six renditions in many segments, call it six times the bytes, and hundreds of hours land every minute. I cannot keep all of it hot, and deleting a creator’s upload is not a trade I get to make. So storage is tiered by popularity: a small fraction of videos drive most of the views, and those stay replicated across regions and ready to serve, while the long tail sits in cheap cold storage where the first byte is slower and a video nobody has opened in years can wait.

    Built in step 4: Storing exabytes affordably
  6. 28–34 min

    Scaling what is left

    The CDN took the bytes, but metadata reads, search and upload coordination still land on my services, and at this point those are one machine. So a load balancer in front, many stateless copies of each service behind it, and a cache for the hot metadata. I would split them by plane rather than by feature — upload and encoding on one side, watch metadata and search on the other — because their traffic shapes have nothing in common. A spike on the creator side then stays a creator-side problem, and the people watching never find out it happened.

    Built in step 5: Scale the control plane
  7. 34–39 min

    Counting without hurting playback

    Counting is the next thing that can hurt me. Owners want views and watch time, the recommender wants the same data, and a database write on every play — plus a counter bump on a viral video — puts my heaviest write in the middle of my hottest read. So the player emits small watch events onto a stream and everything downstream reads from there: counts aggregated in the background and approximated for the very hot videos, recommendations trained on the same log. If aggregation falls behind, the numbers lag and playback does not notice.

    Built in step 6: Views, watch time & recs
  8. 39–43 min

    The parts real users hit

    The last pieces are the ones real users run into. Uploads happen over bad connections, so they are chunked against a session and resumable — a drop retries the missing chunk, not the file. Copyright matching runs as its own pass over the finished upload, fingerprinting it against rights-holder references. And live is the same adaptive-bitrate and CDN idea with the encoder running as the feed arrives and the manifest published continuously, so viewers sit a handful of seconds behind the event.

    Built in step 7: Uploads, copyright & live
  9. 43–45 min

    What I traded away

    So the shape in one breath: facts in a database, bytes in object storage, one asynchronous encode into a ladder of segments, a CDN carrying nearly all the reads, tiering that matches cost to popularity, and events instead of synchronous counting. Almost every call there trades something for scale — cold storage costs a slow first byte, asynchronous counting costs exact numbers, encoding up front costs storage I spend on videos nobody watches. With more time I would go deeper on search and on how a recommendation feed is ranked, and on how the manifest itself is chosen per device and region.

What this teaches

Learn system design by building a video platform like YouTube step by step. An interactive guide covering metadata vs blob storage, the async transcoding pipeline and ABR ladder, CDN edge delivery, tiered hot/cold storage, scaling the control plane, async watch analytics, and resumable uploads, Content-ID and live.

Key takeaways

  • Split tiny metadata (DB) from huge media (blob store).
  • Async transcoding turns one raw file into an ABR ladder of segments.
  • Adaptive bitrate lets the player switch quality without buffering.
  • A CDN serves immutable segments from the edge — 95%+ offload.
  • Tiered hot/cold blob storage keeps exabytes affordable.
  • Async watch events drive view counts and recommendations.
  • Resumable uploads, content-ID, and live streaming for the real world.

Concepts covered

  • How does YouTube stream to a billion screens?
  • Split the bytes from the facts
  • One file becomes many
  • Serving the watch
  • Storing exabytes affordably
  • Scale the control plane
  • Views, watch time & recs
  • Uploads, copyright & live
built to be streamed, not memorized — make the calls, kill the CDN, run the gauntlet.
Finished this one? 0 / 65 System Designs done
NextDesign Uber Next in “System Design in 30 Days” · step 19 of 21

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.

More System Designs