Skip to content
16px
System DesignNetflixCDNVideo StreamingBackend

Netflix's Real Streaming Trick: Send Fewer Bits, Then Move Them Next Door

How Netflix attacks the streaming problem twice — with per-title encoding, VMAF, shot-based optimization, and Open Connect appliances placed inside your ISP — so that by the time you press Play, all the hard work is already done.

July 2, 202612 min read

If you ask a junior engineer how Netflix handles scale, you almost always get the same answer: "big CDN, lots of servers." That's not wrong, exactly. It's just not the interesting part.

The interesting part is that Netflix attacks the problem twice, in two completely different places, before you ever press Play.

First, it makes the video smaller — but only where "smaller" doesn't cost you visible quality. Second, it moves that video physically closer to you, often into your own ISP's building, before anyone in your city has watched it.

One line, the whole idea:

Reduce the number of bits you have to send. Then reduce the distance those bits have to travel.

Everything else — per-title encoding, shot-based encoding, VMAF, Open Connect, steering — is machinery hanging off those two sentences.

Start with the naive mental model, then break it

When you hit Play, don't picture one giant file streaming down from a server in Virginia. That model will lead you to the wrong conclusions about the entire system.

Here's what's actually happening, roughly in order:

  1. There's an original studio master — huge, effectively lossless.
  2. An encoding pipeline turns that master into many versions at different resolutions and bitrates.
  3. Each version is chopped into small chunks, usually a few seconds each.
  4. Those chunks get distributed to cache servers near users.
  5. Your player requests chunks one at a time and, for each one, picks the quality it can currently afford.

That last point is adaptive bitrate streaming, and it's why your video drops to a blurry 480p on hotel Wi-Fi and quietly climbs back to 4K when you get home. The player is making a fresh decision every few seconds: 240p on a dying connection, 1080p on a good one, 4K when the network really has headroom.

So far, so standard. Now here's the design choice most systems get lazy about.

The easy way to run this is to give every title the same bitrate ladder. One fixed table:

Simple to operate. Also wasteful, and in both directions at once.

A clean animated film looks gorgeous at a fraction of that 1080p bitrate — you're spending bits on quality no human can see. A dark action scene with rain, smoke, fast camera motion, and explosions can look bad at 5000 kbps — you're starving the one title that actually needed the bits. Same ladder, opposite failures.

That single observation is the seed of everything Netflix built next.

ResolutionBitrate
360p800 kbps
720p2500 kbps
1080p5000 kbps
4K16000 kbps

Per-title encoding: measure the content instead of guessing

Per-title encoding replaces "one ladder for everyone" with a real question, asked per title:

For this movie, what's the ladder that gives the best perceived quality for the fewest bits?

Take two titles. A fixed system might encode both at 1080p @ 5000 kbps and call it a day. But the animation might be indistinguishable from the master at 1080p @ 2500 kbps, while the action film still looks rough at 5000. So you stop shipping one table and start shipping two:

Animation           Action
360p  @ 400 kbps    360p  @ 900 kbps
720p  @ 1100 kbps   720p  @ 3000 kbps
1080p @ 2500 kbps   1080p @ 6500 kbps

This is not primarily a cost play — though at Netflix's volume, shaving a few hundred kbps off a title watched tens of millions of times is a serious infrastructure win on its own. The bigger prize is user experience. A tighter ladder means users on weak networks buffer less, and users on strong networks get more quality for the same bytes.

The obvious junior objection: "Why not encode everything at a huge bitrate and let the CDN sort it out?"

Because at this scale there's no such thing as a free bit. Every unnecessary bit is multiplied by an audience, then multiplied again by every ISP link it crosses. "Let the CDN handle it" is how you turn a solvable encoding problem into a permanent, recurring bandwidth bill.

VMAF: quality is perceptual, so measure it that way

Here's the hard part of per-title encoding: how do you know a lower bitrate still looks good? You can't eyeball ten thousand titles.

The old instinct is to reach for PSNR — a pixel-level math difference between the original and the encode. The problem is that humans don't watch video like a pixel-diff calculator. Some distortions are glaring; others are invisible; some scenes hide compression artifacts beautifully and others expose every one of them. PSNR doesn't know the difference.

So Netflix built VMAF — Video Multi-Method Assessment Fusion — to estimate perceived quality rather than mathematical difference. That word "perceived" is the whole point.

Because it reframes the goal. The target was never:

smallest file

The target is:

smallest file that still looks good to a human

Sit with that, because it's a mindset that generalizes far beyond video. Compression is not removing data. It's about removing the data nobody will miss.

With a perceptual score in hand, the pipeline can do something honest: encode a title at many resolution/bitrate combinations, score each one, plot quality against bitrate, and pick the points that sit on the good part of that curve. That's a content-aware ladder instead of a guessed one.

Shot-based encoding: even one movie isn't "one thing"

Per-title encoding is a big step up. But it still cheats a little, because it treats a two-hour movie as if it has one level of complexity.

It doesn't. A film is a calm dialogue scene in a bright room, then a dark chase in the rain, then a static wide landscape, then a frenetic fight. Pick one strategy for the whole title and you're averaging all of that together — over-spending on the easy scenes, under-spending on the hard ones.

So Netflix pushed the same idea one level deeper with shot-based encoding, driven by what they call the Dynamic Optimizer, which searches across resolution and quality points to find an optimized compression path — with VMAF as the objective it's optimizing for, because again, the goal is perceptual quality, not file size.

The mental model shifts from "this movie needs X" to per-shot decisions:

  • Calm dialogue → easy, low bitrate is plenty
  • Rain-soaked chase → complex, give it more bits
  • Static landscape → easy again, pull back
  • Fast fight → allocate generously

A "shot" here is roughly a continuous camera segment with consistent lighting, motion, and complexity — the natural unit at which video actually varies.

If this smells familiar, it should. It's the same principle behind a lot of good distributed systems:

Don't optimize with one global assumption when the workload is heterogeneous.

Query planners do it per query. CDNs do it per route. Autoscalers do it per service. Netflix does it per shot. Same instinct, different layer.

The catch: you're moving compute earlier, not removing it

None of this is free, and I'd distrust anyone who presents it as free.

Per-title and shot-based encoding mean analysis jobs, encoding the same content many times at different settings, quality scoring, and storage for every resulting representation. You need a pipeline that can fail, retry, and still produce deterministic output.

Netflix can pay that price happily because almost all of its catalog is video-on-demand. The encoding happens long before you press Play, and the same encoded files get watched millions of times afterward. That flips the economics completely:

Spend more compute offline so the online experience is cheaper and faster.

It's the same trade you make when you build a database index. Creating the index burns CPU and disk up front; every query afterward gets faster for free. Netflix is essentially building delivery indexes for video, ahead of demand — pay once at encode time, cash in on every stream.

Second trick: get the bits physically closer

Smaller files are great. The bits still have to reach you.

If every stream had to travel from a central cloud region to every living room, the system would be expensive, slow, and fragile — and you'd be at the mercy of every congested transit link in between. So Netflix built its own CDN, Open Connect, whose entire job is delivering shows and movies to members worldwide.

Two pieces matter:

  1. Settlement-free interconnection with ISPs — Netflix peers directly instead of paying transit to shove video across the open internet.
  2. Open Connect Appliances (OCAs) — purpose-built cache boxes placed inside or right next to ISP networks. Qualifying ISPs get embedded appliances at no charge, because a box full of Netflix content sitting in their datacenter is cheaper for them too.

An OCA is, at heart, a specialized cache server stuffed with video. So the delivery path collapses from this:

User → ISP → transit provider → distant CDN/origin → video

to this:

User → ISP → nearby Netflix OCA → video

The fastest network request is the one that never crosses half the internet. An OCA in your ISP's rack is about as close as "not on your own device" gets.

Pre-positioning: don't wait to be asked

Here's where Open Connect stops being a normal cache.

A normal cache is reactive: the first user takes the miss and pays the slow origin fetch, everyone after that gets a fast hit. Fine for a website. Bad for a show that drops at midnight and gets slammed by ten million people in the first hour — under that model, ten million people race for the origin at once.

So Netflix pre-positions content instead. The rough loop:

  1. A popularity model predicts demand by region and ISP.
  2. That prediction decides which titles should live on which OCAs.
  3. Encoded chunks get pushed to those OCAs overnight, during off-peak hours when the network is cheap and idle.
  4. When users finally press Play, it's already a local hit.

New season launching tomorrow? Netflix doesn't wait for the stampede — it fills the caches before the doors open. The goal is that even the first viewer doesn't pay the expensive miss. That's a fundamentally different posture from "cache on demand," and it's only possible because on-demand video makes future demand predictable.

The part I want juniors to actually internalize: clean plane separation

Notice what an OCA is not. It's not an account database. It's not the recommendation engine. It's not billing. It doesn't know who you are.

It serves video files. That's it. And that restraint is the good architecture.

Control plane (centralized, complex, business-sensitive)
  - auth
  - catalog
  - recommendations
  - playback authorization
  - session / device logic
  - routing decisions

Data plane (local, simple, high-throughput)
  - encoded video chunks
  - image assets
  - cache delivery

The rule of thumb worth stealing: when a plane is heavy, dumb, and high-throughput, push it to the edge, close to the user. When it's complex and business-sensitive, keep it centralized where you can reason about it and change it safely.

Netflix can redeploy recommendation logic without touching a single OCA, and can add thousands of OCAs without teaching any of them a thing about billing. The two planes evolve independently. That decoupling is worth more than any single clever optimization in the system.

Steering: which copy do you actually stream from?

Once a title lives on many OCAs, one question remains: which one should this client use?

That's the steering service's job. It looks at signals like client IP, ISP/ASN, geography, cache health, spare capacity, whether the cache even has the title, and path quality — then hands the client a manifest pointing at the best copy.

Client opens Netflix
      ↓
Playback service checks entitlement / session   (control plane)
      ↓
Steering service picks a nearby, healthy OCA
      ↓
Client gets a manifest
      ↓
Client pulls chunks from the chosen OCA          (data plane)

If a cache is overloaded, unhealthy, or missing the title, steering just sends the client somewhere else. The user never learns any of this happened. From their seat the movie plays. From the system's seat, a dozen decisions landed before the first frame.

Build a toy version this weekend

You can't rebuild Open Connect, but you can build something small that teaches the same reflexes.

1. Encode the same clip at multiple bitrates with ffmpeg.

bash
1ffmpeg -i input.mp4 -b:v 400k  output_400k.mp4
2ffmpeg -i input.mp4 -b:v 1100k output_1100k.mp4
3ffmpeg -i input.mp4 -b:v 2500k output_2500k.mp4
4ffmpeg -i input.mp4 -b:v 5000k output_1080p.mp4

Then compare with PSNR, SSIM, or VMAF if your ffmpeg build has it. Don't chase Netflix-grade quality; just feel the loop: encode → measure quality → compare bitrate → choose ladder.

2. Store a per-title ladder based on what you measured.

json
1{
2  "title_id": "movie_123",
3  "complexity": "low",
4  "ladder": [
5    { "resolution": "360p",  "bitrate": "400k" },
6    { "resolution": "720p",  "bitrate": "1100k" },
7    { "resolution": "1080p", "bitrate": "2500k" }
8  ]
9}

A busier title earns a heavier ladder (900k / 3000k / 6500k). Now your system has plans, not a single hardcoded table.

3. Stand up a few dumb cache nodes.

Three tiny HTTP servers, each holding a different subset of chunks — say one biased to UAE-popular titles, one to India-popular titles, and one fallback. That's your data plane.

4. Write a steering service.

Give it a client region, a requested title, and cache health; have it return the best URL.

python
1def steer(region, title, health):
2    if region == "UAE" and title in cache_a and health["a"]:
3        return "https://cache-a.local/title/chunk.m4s"
4    if region == "IN" and title in cache_b and health["b"]:
5        return "https://cache-b.local/title/chunk.m4s"
6    return "https://cache-c.local/title/chunk.m4s"   # fallback

Crude, but it captures the whole thesis: optimize the media, place it near demand, route to the closest healthy copy.

Why this is the good kind of engineering

Netflix's design isn't impressive because it's big. It's impressive because the architecture is shaped to fit the workload's actual physics:

  • Files are huge → so optimize the bits (per-title, shot-based).
  • Content is rewatched millions of times → so spend compute offline, once.
  • Quality is perceptual, not mathematical → so measure with VMAF, not PSNR.
  • Network distance is real cost → so put OCAs inside ISPs.
  • Demand is predictable → so pre-position before the spike.

Every property of the problem has a matching move in the architecture. Nothing is bolted on.

And that's the difference between scaling and engineering. The junior instinct, when something is slow, is to reach into the hot path: add a cache, add replicas, add a load balancer, bump the instance size. All useful. But the strongest systems win before the request ever arrives.

Netflix wins before you press Play. By the time you click, the video's been analyzed, the ladder chosen, the chunks encoded, the popular files parked in a box down the road at your ISP, and the steering logic already knows which cache is healthy. There's no heroics left to do in real time — the expensive decisions were made hours ago, off the hot path.

You see one button: Play.

The system sees encoding science, perceptual metrics, cache placement, ISP peering, routing, health checks, and adaptive delivery — every layer quietly shaving off a little waste. Fewer bits at the encoder, adaptive chunks at packaging, a shorter path at the cache, a healthier route at steering, the best affordable quality at the client.

Stack enough of those small wins and you get a system that looks effortless from the outside and is very, very hard to beat from the inside.

Don't just scale the system. Understand the workload well enough that most of the expensive work never has to happen while someone's waiting.

Bhupesh Kumar

Bhupesh Kumar

Backend engineer building scalable APIs and distributed systems with Node.js, TypeScript, and Go.