SYSTEM DESIGN · DESIGN PROBLEMS · MEDIA AND STORAGE · MEDIUM · 17 OF 41

Design Netflix: Control Plane, Caches Inside ISPs and Fast Playback Start

How to design a subscription streaming service like Netflix: requirements, peak concurrent stream math, splitting a cloud control plane from a CDN data plane, encoding a known catalog ahead of time, pre-positioning files in caches inside ISPs during quiet hours, steering each play to the best cache, DRM licences, a resilient continue-watching history, and the trade-offs, using only widely published ideas.

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
1 / 18

Press play to hear the narration, or step through at your own pace.

Notes

Listen

Requirements. A member browses a personalised home page of rows, picks a title and presses play on any device, choosing audio language and subtitles. They can stop on the TV and resume on their phone at the same second. Content must be protected with DRM, because studios require it. Billing, sign-up and live events are out of scope, and there are no user uploads at all, which is a big simplification.

Qualities. Playback should start in a second or two and almost never stall, at the best quality the connection allows. The design point is peak hour: evenings, and especially the night a big series launches. Browsing and playback should survive losing an entire cloud region. The resume point can be eventually consistent; being off by a few seconds is fine.

Functional requirements
  • in scope:
  • • browse a personalised home
  • page of rows
  • • play a title on TV, phone,
  • laptop; pick audio + subs
  • • resume where you left off,
  • on any device
  • • protect content (DRM)
  • out: billing, sign-up, user
  • uploads, games, live events
Non-functional requirements
  • play starts in ~1-2 s
  • rebuffering very rare
  • best quality the link allows
  • peak hour is the design point:
  • evenings, weekends, launches
  • browsing and playing must
  • survive a failed cloud region
  • resume point: eventual, fine

Ask scale

Assume three hundred million members, a hundred million watching on a given day for two hours each. That's two hundred million hours a day. Spread evenly, about eight million streams at once, but viewing bunches up in the evening, so plan for about three times that: twenty-five million concurrent streams. At five megabits each, that's over a hundred terabits a second at peak. That number decides the whole architecture.

Now the surprising number. Ten thousand titles averaging ten hours, counting every episode, is around a hundred thousand hours of content. Even with every resolution, codec, audio track and subtitle, that's only a few petabytes in total. The popular slice for one region is a few hundred terabytes, which fits on a rack of cache servers. So you can put the content right next to viewers before they ask for it.

Traffic
members              300M
daily viewers        100M
hours/viewer/day     2
  = 200M hours/day
avg concurrent = 200M / 24
                     = ~8M
peak (x3)            = ~25M

avg bitrate          5 Mbps
peak egress = 25M x 5 Mbps
                     = ~125 Tbps
Catalog size
titles                ~10K
avg hours per title   ~10
  = ~100K hours of content
all renditions, codecs,
  audio, subs   ~30 GB/hour
  = ~3 PB total catalog

popular slice per region
  = a few hundred TB
-> fits on a cache cluster
   inside one ISP

Define API

The API. The home call returns rows of titles with artwork for this profile. The key call is playback start: the device describes its capabilities, like supported codecs, HDR and screen size, and gets back a manifest tailored to it, a ranked list of cache URLs, and the available audio and subtitle tracks. A licence call exchanges a DRM challenge for decryption keys. And the player sends a heartbeat with the position every so often.

Core API
GET  /v1/home?profile=..
  -> rows[{ title, artwork }]
POST /v1/playback/start
  { titleId, device, caps }
  -> { manifest, cacheUrls[],
       audio[], subs[] }
POST /v1/license
  { challenge } -> { keys }
POST /v1/heartbeat
  { titleId, positionSec }

Data model

Data model. Titles and their encoded assets are small and change rarely, so they're cached everywhere. Viewing history is the big, write-heavy one: a row per profile and title with the last position. It fits a wide-column store like Cassandra, replicated across regions, which Netflix has publicly described using for this. A cache map records which files each cache server holds and whether it's healthy. And precomputed home rows are stored per profile.

Records
title    (titleId, type, meta)
asset    (titleId, codec, res,
          bitrate, fileKey)
history  PK (profileId),
          cluster (titleId)
          -> positionSec, updatedAt
  wide-column, multi-region
cachemap (cacheId, region,
          fileKeys[], health)
rows     profileId -> ranked rows

High-level design

Draw the control plane first. It runs in the cloud and handles everything except video bytes: sign-in, the home page, search, deciding what to play, licences and history. When you press play, the playback service picks the right files for your device, asks steering which caches should serve you, and arranges a DRM licence. These are small, latency-sensitive API calls, and Netflix has publicly described running this part on AWS across several regions.

Now the data plane. Encoded files sit in origin storage, but viewers almost never touch it. Each night, a fill planner predicts what each region will watch tomorrow and copies those files to cache servers placed inside internet providers and at internet exchange points. Then when you press play, your TV streams from a cache that might be in your own city. Netflix calls its version of this Open Connect, and it's publicly documented.

Deep dive: caches

Deep dive one: placement. Because the catalog is known, you don't wait for a cache miss. A planner forecasts demand per region from popularity and the release calendar, and pushes files during the quiet early-morning hours when the links are idle. Caches inside providers hold the hottest titles; caches at exchange points hold a wider set. Caches can fill from nearby peers instead of origin. For a big launch, the files are on the edge days before release.

Why is this better than a normal pull-through CDN? A pull CDN fetches on the first miss, which at nine pm on launch night means a storm of misses. Pre-positioning means the file is already there. Providers like it because the traffic stays inside their network. And encoding is tuned per title: an animated show compresses far better than a grainy action film, so each gets its own bitrate ladder, which Netflix has written about publicly.

Pre-positioning
  • predict demand per region:
  • popularity, new releases
  • fill during off-peak hours
  • (early morning local time)
  • tiers: ISP cache holds the
  • hottest, exchange cache
  • holds a wider slice
  • caches fill from peers before
  • going back to origin
  • launch day: fill days ahead
Why this beats a plain CDN
  • no cold misses at peak: the
  • file is already there
  • ISP saves transit; serving
  • stays inside its network
  • fill uses idle night capacity
  • per-title encoding: ladder
  • tuned to each title, so a
  • cartoon needs fewer bits
  • than an action film

Deep dive: play start

Deep dive two: starting playback. The playback service takes your device's capabilities and picks matching files. Steering looks at your network location and the cache map, and returns a ranked list of caches that actually hold those files, are close and aren't overloaded. The licence request runs in parallel. The player fetches a few low-bitrate segments, starts, then climbs to higher quality. If a cache fails mid-stream, the player moves to the next one on the list.

A word on DRM. Files are encrypted once, during encoding, so caches only ever store ciphertext; a stolen cache disk is useless. The player sends a licence challenge, and the licence service checks the membership, the device and the region before returning keys bound to that device. The licence call is on the critical path of every play, so it has to be fast and highly available, just like steering.

From click to first frame
  • 1 playback/start: device caps
  • 2 steering: caches that hold
  • these files, near the user,
  • healthy, not overloaded
  • 3 licence request in parallel
  • 4 player fetches low-bitrate
  • first segments, starts
  • 5 climbs the ladder (ABR)
  • cache fails -> next in list
DRM in one slide
  • files encrypted once at
  • encode time
  • caches store ciphertext only
  • device sends licence challenge
  • licence server checks member,
  • device, region, then returns
  • keys bound to the device
  • licence service is on the
  • critical path: keep it fast

Deep dive: history

Deep dive three: viewing history. Twenty-five million streams sending a heartbeat every thirty seconds is over eight hundred thousand writes a second at peak. Each heartbeat upserts one row for the profile and title, and the newest timestamp wins. A wide-column store that accepts writes locally in each region and replicates asynchronously handles that easily. If you switch devices, the new one reads the latest position, which may be a few seconds behind. That's fine.

Continue watching
25M streams, 1 beat / 30 s
  = ~830K writes/s at peak

write: upsert (profile, title)
  last-write-wins by timestamp
read: on home page + play

store: wide-column, local
  writes in each region,
  async replication
also feeds the event stream

Trade-offs

Failures. If a whole cloud region fails, members are shifted to the other regions, which are sized to absorb the extra load. If a dependency like personalisation is slow, serve a fallback, such as a generic popular row, instead of an error. If a cache dies, steering stops sending people there and active players switch. Netflix popularised deliberately injecting failures in production to prove this works. The headline metric is successful play starts per second.

Trade-offs. Pre-positioning copies the same files onto thousands of caches, spending storage to eliminate misses, and it only works because the catalog is small and known. Per-title encoding spends compute up front to save bandwidth on every view. Eventually consistent history accepts a few seconds of drift so each region writes locally. At ten times the scale: more caches inside providers and more efficient codecs like AV1.

Failures and monitoring
  • cloud region down: shift
  • members to other regions,
  • each sized for extra load
  • dependency slow: fallbacks,
  • e.g. a generic home row
  • cache down: steering skips it,
  • player switches mid-stream
  • practice: inject failures on
  • purpose (chaos testing)
  • watch: play starts/s, rebuffer
Trade-offs to name
  • pre-positioning: storage on
  • many caches for zero misses
  • (works because catalog is
  • small and known)
  • per-title encoding: compute
  • for fewer bits
  • eventual history: seconds of
  • drift for regional writes
  • 10x: more ISP caches, AV1

Say it like this

The summary. Peak is about twenty-five million streams and over a hundred terabits a second. A multi-region cloud control plane handles browsing, playback decisions, licences and history. The catalog is encoded ahead of time with per-title ladders and encrypted. Each night, files are pre-positioned in caches inside providers and at exchanges. Steering gives each play a ranked list of healthy caches that hold the file. History is heartbeat upserts in a regional wide-column store.

The 60-second answer
  • peak ~25M streams, ~125 Tbps
  • control plane in the cloud,
  • multi-region active-active
  • catalog encoded ahead,
  • per-title ladders, encrypted
  • nightly fill to ISP and
  • exchange caches
  • steering: ranked healthy
  • caches with the file
  • history: heartbeats, LWW

Interview questions

How is Netflix different from YouTube as a design problem?

Netflix has a small, curated catalog known in advance and no user uploads, so content can be encoded and placed on caches before anyone asks for it. YouTube has an enormous, unpredictable catalog, so it relies on pull-through caching and fast processing of new uploads.

What is the difference between the control plane and the data plane here?

The control plane is everything except video bytes, such as browsing, playback decisions, licences and history, running as services in cloud regions. The data plane is the network of cache servers near viewers that actually streams the files.

Why place caches inside ISPs?

Traffic is served from inside the viewer’s own provider network, which cuts latency and transit costs for everyone. Combined with filling them overnight, it means peak-hour traffic rarely leaves the provider at all.

How do you decide which cache serves a viewer?

A steering service combines the viewer’s network location with a map of which caches hold the requested files and how healthy and loaded they are, and returns a ranked list. The player uses the first and fails over to the next if needed.

How would you store continue-watching positions?

Heartbeats upsert one row per profile and title with the position and a timestamp in a wide-column store, using last-write-wins. Writes go to the local region and replicate asynchronously, so a few seconds of lag between devices is acceptable.

How do you survive a whole cloud region failing?

Run the control plane active-active in several regions, each with spare capacity, and shift members to healthy regions with DNS or traffic routing. The data plane is independent, so streams already playing from caches keep going.

What is per-title encoding?

Instead of one fixed bitrate ladder for everything, each title is analysed and gets a ladder tuned to its complexity. Simple content like animation reaches the same visual quality at much lower bitrates, saving bandwidth on every view.

Where does DRM fit and how do you keep it from slowing playback?

Files are encrypted at encode time and caches store only ciphertext; the player obtains keys from a licence service. The licence request runs in parallel with the first segment fetches and the service is replicated close to users.