18 / 19
Playbook / 18

Design Netflix

260M subscribers, ~200M concurrent streams at peak, 15% of the global internet's downstream traffic. The control plane (users, billing, recommendations) is small enough to fit in standard AWS. The data plane (the actual video bytes) does not — Netflix runs its own CDN, Open Connect, with cache boxes inside ISP networks worldwide. The whole architecture is built around getting the video as physically close to the viewer as possible.


1 · Clarifying questions

Functional scope?Browse catalog, search, recommendations, play video, resume playback, parental controls, downloads. No live TV, no user-generated content.
Catalog size?~15K titles globally, ~6K per region (rights vary). Each title has multiple seasons/episodes — total ~100K playable items.
Scale?260M subscribers, ~200M concurrent streams at peak. Average viewing session ~90 minutes; ~6 sessions/user/week.
Quality?From 240p mobile to 4K HDR + Dolby Atmos. Multiple codecs (H.264, H.265, AV1). Adaptive bitrate.
Latency?Browse: P99 ≤ 300 ms. Start playback: P99 ≤ 2 s from tap-to-play. Re-buffer ratio < 0.5%.
Availability?99.99%. The control plane can fail more gracefully than playback — a user who can't browse is annoyed; a user mid-show whose playback stops is angry.
Multi-region?Yes. Catalog metadata is regional (rights). Playback served from the nearest Open Connect appliance.

2 · Capacity math, on a napkin

NumberCalculationResult
Subscribersgiven260M
Concurrent streams peakgiven200M
Average bitrate (blended)~5 Mbps (mostly HD, some 4K, some mobile)5 Mbps
Peak egress200M × 5 Mbps~1 Pbps (1,000 Tbps)
Daily egresspeak ÷ 2 × 86,400~5,400 PB/day → ~160 EB/month
Catalog item countgiven~100K (with episodes)
Per-title variants~10 bitrate ladder × 3 codecs × HDR/SDR~50 variants
Per-title storage (master)~50 GB per movie / per episode (uncompressed)~50 GB
Per-title storage (encoded variants)~500 GB across all variants~500 GB
Total catalog storage~100K × 500 GB~50 PB encoded; ~5–10 PB per Open Connect appliance
Control plane QPS (browse, play start)~10M actions/min average~170K QPS
Recommendation requestsper browse session, ~100M/day~1.2K QPS average — bursty

The single most important number: 1 Pbps egress at peak. No commercial CDN provider can sustain that for one customer at reasonable cost. The reason Open Connect exists at all is bandwidth economics — at this volume, building your own CDN is cheaper than paying anyone else's.

3 · API and data model

Player ↔ control plane

GET  /v1/home                          # personalised rows for the home screen
  → 200 { "rows": [{"title": "Continue Watching", "items": [...]}, ...] }

GET  /v1/title/:id                     # title page metadata
  → 200 { "id": ..., "synopsis": ..., "episodes": [...], "available_until": "..." }

POST /v1/playback/start                # tap-to-play
{ "title_id": "t_...", "device": {...}, "client_caps": {"codecs": [...], "max_bitrate": ...} }
  → 200 {
    "session_id": "s_...",
    "manifest_url": "https://oca-region.../manifest.mpd",
    "drm_license_url": "https://...",
    "resume_at": 1820
  }

POST /v1/playback/heartbeat            # every 30 s during playback
{ "session_id": "s_...", "position_ms": ..., "bitrate": ..., "rebuffers": ... }
  → 204

POST /v1/playback/end                  # tab closed / video ended
{ "session_id": "s_...", "position_ms": ..., "complete": true }

Storage (control plane)

titles                          -- regional master catalog
  title_id        UUID PK
  type            VARCHAR(16)    -- movie | series | episode
  parent_id       UUID NULL      -- for episodes → series
  region          VARCHAR(8)
  rights_until    TIMESTAMP
  metadata        JSONB

variants                        -- one row per encoded artifact
  variant_id      UUID PK
  title_id        UUID
  codec           VARCHAR(16)    -- h264 | h265 | av1
  resolution      VARCHAR(8)     -- 240p .. 2160p
  bitrate_kbps    INT
  hdr             BOOLEAN
  duration_ms     BIGINT
  manifest_key    TEXT           -- key in object store
  segment_count   INT

profiles                        -- per-account profile
  profile_id      UUID PK
  account_id      UUID
  display_name, avatar_url
  maturity_rating VARCHAR(8)

viewing_history                 -- Cassandra; partitioned by profile_id
  profile_id, title_id, watched_at
  position_ms, complete
  device, region
  PRIMARY KEY ((profile_id), watched_at DESC, title_id)

recommendation_cache            -- materialised per profile, refreshed nightly
  profile_id      UUID
  rows            JSONB          -- precomputed home-screen rows

4 · High-level architecture

Player asks the edge gateway to start playback. Playback service authenticates, fetches the title's manifest, asks the routing service for the best Open Connect appliance for this client's network. OCAs are pre-filled with the catalog (the long tail of titles is on S3 in case of cache miss). The player downloads HLS/DASH segments directly from the OCA; the control plane sees only heartbeat + start/stop events.

5 · The hard part — Open Connect, the CDN

Why a private CDN?

At 1 Pbps peak egress, commercial CDN pricing falls apart. Netflix's solution: ship physical cache boxes (OCAs — Open Connect Appliances) to ISPs and exchange points. ISPs install them inside their own networks. When a Netflix subscriber on that ISP starts a stream, the bytes never leave the ISP's network. The ISP saves on transit; Netflix saves on egress; the user gets better quality.

  • OCA hardware. Custom-built dense storage (~250 TB per box, ~100 Gbps serving). Open Connect is FreeBSD-based for the network stack.
  • Fill window. Each night during low-traffic hours, OCAs pull the next day's expected titles from regional S3 mirrors. Popularity-weighted; the long tail stays at S3.
  • Routing. Player asks the routing service. Service knows which OCAs are reachable for this client (BGP + geolocation), which ones have the requested title, and which one is least loaded. Returns a sorted list of 3 — the player falls back if the first fails.

Adaptive bitrate (ABR)

Video is encoded into a ladder of variants — same title, multiple resolutions and bitrates. The manifest lists them. The player measures throughput and switches between variants on segment boundaries (every 2–10 s) to maximise quality while avoiding rebuffer.

# Simplified MPEG-DASH manifest excerpt
<MPD>
  <Period>
    <AdaptationSet contentType="video">
      <Representation id="240p"  bandwidth="400000"  width="426"  height="240">
        <SegmentList timescale="1000" duration="2000"> ... </SegmentList>
      </Representation>
      <Representation id="480p"  bandwidth="1000000" width="854"  height="480">  ...  </Representation>
      <Representation id="720p"  bandwidth="2800000" width="1280" height="720">  ...  </Representation>
      <Representation id="1080p" bandwidth="5000000" width="1920" height="1080"> ...  </Representation>
      <Representation id="4k"    bandwidth="16000000" width="3840" height="2160"> ... </Representation>
    </AdaptationSet>
  </Period>
</MPD>

# Per-shot encoding — Netflix's special sauce
# Instead of a fixed bitrate per resolution, each scene gets its own bitrate
# based on how compressible it is. A talking-head scene at 1080p might be
# 1 Mbps; an action scene at the same resolution might be 8 Mbps.

DRM

Studios require it. Three DRM systems (Widevine for Android/Chrome, FairPlay for Apple, PlayReady for Edge/consoles). License acquired separately from segments; tied to the playback session. The license carries usage rules: max output resolution per device class, offline-download expiry, screen-recording protection.

6 · The encoding pipeline

A new title arrives as a mastered file (~50 GB, ProRes 422 HQ). Encoding produces ~50 variants spread across codecs (H.264, H.265, AV1), resolutions (240p..2160p), HDR vs SDR, and audio (stereo, 5.1, Atmos). Each variant is segmented into 2–10 s chunks and packaged into HLS + DASH formats. Total encoding compute per title: ~5,000 CPU hours.

  • Per-shot encoding. Detect scene boundaries, encode each scene with bitrate matched to its complexity. Saves ~20% bandwidth at the same perceptual quality. The data-engineering layer behind this is enormous.
  • Quality measurement. Every variant gets a VMAF score (perceptual quality metric). Variants below threshold are re-encoded with different parameters.
  • Distribution. Encoded variants land in regional S3. The OCA fill service consumes from there.

This pipeline is offline. A new title takes hours to days from arrival to playable; the SLO is "ready 24 hours before scheduled release."

7 · Recommendations

A different system entirely. Two layers:

  • Offline candidate generation. Per profile, nightly job produces a candidate set of ~500 titles using collaborative filtering + content-based signals. Stored in the recommendation cache.
  • Online ranking. At browse time, the recs service fetches the candidate set, runs a real-time ranker (fast model that uses context: time-of-day, device, recent watches), and returns the top-N for each row. Adds ~10 ms to the home-screen response.

Row ordering and row composition (Continue Watching, Because You Watched, Trending, Top 10) is itself a separate ML problem. Netflix runs continuous A/B tests on row design.

8 · Failure modes & runbook

FailureSymptomMitigation
OCA failurePlayer times out on segment downloadRouting service returned 3 OCAs; player fails over silently. OCA marked unhealthy; rerouting takes effect within seconds.
Regional control plane outageBrowse fails; existing streams continuePlayer has the manifest already; new segments come from OCA without control plane. Browse fails over to next region.
S3 origin slowOCA cache miss → fill from S3 slow → player switches to lower bitrateABR absorbs gracefully; SLO is rebuffer rate, not bitrate.
New popular title not in OCAsCache miss storm → S3 origin saturatedPre-warm OCAs before high-profile release. Throttle uncached titles' bitrate temporarily.
DRM provider outagePlayer can't acquire license → no playbackMulti-DRM (one platform per provider). Caching license servers regional. License caching on device for offline.
ISP peering failureSubscribers on one ISP can't reach any OCARouting service falls back to OCAs at internet exchange points; quality degrades to "OK over the public internet."
Recs cache poisonedAll users see the same rowPer-region cache invalidation; fall back to non-personalised popular rows during recovery.
Encoding pipeline backed upNew release not ready in timePipeline SLO of "24h before release"; alert at 48h. Manual escalation if a title slips.

9 · Cost & SLOs

LineEstimateNote
Control plane (AWS)~$30M/monthMicroservices fleet; Cassandra + EVCache; the published "Netflix on AWS" story
Open Connect hardware (CapEx amortised)~$25M/month equivalent~20K OCAs worldwide; ~$10K/unit; 3-year amortisation
Open Connect operations + colo~$5M/monthPower, ISP partnerships, field engineering
Encoding compute (AWS EC2 spot, GPU)~$10M/monthPer-shot encoding is CPU-heavy; spot-instance heavy
S3 storage (masters + encoded variants)~$8M/month~50 PB; lifecycle to Glacier for old titles
Recommendations + ML training~$8M/monthOffline candidate gen + online ranking + experimentation
Egress (the bill we'd pay without Open Connect)~$500M/month (hypothetical)The reason Open Connect exists

SLOs

  • Start-up time P99: 2 s. Tap-to-play.
  • Rebuffer rate: < 0.5%. Per stream; the headline quality metric.
  • Browse P99: 300 ms. Home screen render.
  • Availability: 99.99%. Control plane; data plane higher.
  • Encoding ready: 24 h before scheduled release. Hard SLO.

10 · Trade-offs & "what would you change at 10×"

If…Then…
10× subscribers (2.6B)OCA density per region has to roughly double. The catalog doesn't get 10× larger but bandwidth does. The strategic question becomes peering — securing 100 Gbps + lines into every major ISP globally.
Add live sportsWhole new system. Live ingestion, low-latency packaging (LL-HLS), real-time encoding, near-zero buffer. Recommendations matter less; reliability matters more (no second chances).
Add interactive (Bandersnatch-style)Manifest selection at branch points; pre-buffering of multiple paths. The control plane carries playback state more tightly than for linear video.
Add ads (which Netflix added)Ad-decisioning service on the hot path; SCTE-35 markers in the manifest; ad CDN (often a different provider); brand-safety + fraud detection on a real-time basis. Big architectural addition.
P2P delivery for contentTried by some streaming services. Quality is worse than CDN; saves bandwidth but at huge complexity. Netflix has steered clear; their OCA model is more efficient than any P2P scheme at their scale.
"What would a more senior answer add?"The producer's view: content licensing as a system input (the catalog changes by region every month based on contract renewals), the encoding cost per title vs viewership economics (don't waste 5K CPU-hours on a title 10K people will watch), the chaos engineering practice (Netflix invented Simian Army). And the deep observability layer — Atlas, Mantis, Suro — that lets engineers see what's happening on 200M concurrent streams in real time.

Further reading

  • Netflix Technology Blog — multi-year archive on every layer of this design. The single best primary source for any video-streaming system design.
  • "How Netflix Works with ISPs" — Open Connect public site. The OCA partnership model explained.
  • "Per-Title Encode Optimization" — Netflix Tech Blog. The per-shot encoding story; required reading.
  • "Chaos Engineering" — Netflix-authored book. The discipline that came out of running this system reliably.
  • Adjacent: Object storage. The master + variant tier.
  • Adjacent: CDN. The general pattern; Open Connect is the bespoke version.
  • Adjacent: Scale to millions on AWS. The control-plane evolution story.
Found this useful?