~learn.

Netflix Streaming, the whole design.

A video platform that starts any title in under 2 seconds for ~10 million concurrent streams, because the cloud only decides what to play and appliances inside ISPs deliver the bytes.

7 diagrams · 8 sections · revise in ~10 min · Download PDF prints it in the light theme, diagrams included

SQ-06 · Netflix Streaming · design sheethimanshukukreja.in/learn/sheets/bonus-06-netflix-streaming

At a glance#

Number Value What it drives
Concurrent streams at peak ~10M (design target) 3 % of 300M subscribers on a Friday 8 PM
Peak egress 50 Tbps 10M × 5 Mbps; rules out serving video from cloud regions
Start · seek < 2 s · < 500 ms pre-buffer ~5 s at 480p, then adapt
Versions per title ~30 · ~20 GB 8 resolutions × 3–4 bitrates, 2–4 s chunks
Library ~360 TB one copy · ~36 PB at the edge ~100× replication close to viewers
Open Connect 18,000+ servers · 6,000+ locations each appliance: 120 TB, ~200 Gbps ≈ 40,000 streams
Control plane ~1M API req/s · 1,000+ services API p99 < 100 ms, 99.99 % uptime

Architecture#

DiagramNetflix on one page: AWS decides, Open Connect delivers
%% title: Netflix on one page: AWS decides, Open Connect delivers
flowchart TD
  CL@{ icon: "sd:tv", label: "Clients<br/>TV · phone · tablet · web · console" } -->|"browse · press play"| ZU@{ icon: "sd:gateway", label: "Zuul API gateway<br/>auth · rate limit · routing" }
  ZU --> MS["Control plane on AWS · 1,000+ services<br/>catalog · reco · search · billing<br/>every call behind a circuit breaker"]:::core
  ZU ==> PB["Playback service<br/>entitlement · DRM · manifest"]:::hot
  MS --> EV@{ icon: "sd:cache", label: "EVCache<br/>API responses" }
  MS --> CS@{ icon: "tech:cassandra", label: "Cassandra<br/>users · viewing history" }
  MS --> MY@{ icon: "tech:mysql", label: "MySQL<br/>billing" }
  PB -.->|"playback URLs · ranked OCA list"| ISP
  ENC["Encoding pipeline<br/>per-title ladder · ~30 versions · 2–4 s chunks"]:::service --> ORI@{ icon: "tech:s3", label: "Origin · S3<br/>full library · ~360 TB" }
  ORI -.->|"nightly fill"| IXP@{ icon: "sd:server", label: "IXP appliances<br/>most of the catalogue" }
  IXP -.->|"off-peak fill · predicted popular"| ISP@{ icon: "sd:server", label: "ISP-embedded appliances<br/>18,000+ servers · 90 %+ hit" }
  ISP ==>|"video chunks"| PL@{ icon: "sd:users", label: "Player<br/>ABR picks a rung per chunk" }
  class CL,PL client
  class ZU edge
  class EV,IXP,ISP cache
  class CS,MY,ORI store
DiagramThe player's ABR loop: pick a rung for the next chunk
%% title: The player's ABR loop: pick a rung for the next chunk
flowchart TD
  CH["Chunk downloaded<br/>size ÷ time = throughput sample"]:::service --> BW["Bandwidth estimate<br/>harmonic mean of last 5 samples"]:::core
  BW --> B{"Seconds buffered?"}
  B -->|"< 5 s · panic"| LOW["Drop straight to the lowest rung"]:::bad
  B -->|"5–15 s · low"| HOLD["No step up<br/>step down if needed"]:::queue
  B -->|"healthy"| UP{"Highest rung with<br/>bitrate × 1.2 ≤ estimate"}
  UP -->|"10 s since last switch"| SW["Switch at next chunk boundary"]:::ok
  UP -->|"inside cooldown"| KEEP["Up blocked · down allowed"]:::service

Key flows#

DiagramPress play: manifest from AWS, chunks from the ISP
%% title: Press play: manifest from AWS, chunks from the ISP
sequenceDiagram
  autonumber
  participant P as Player
  participant Z as Zuul
  participant S as Playback service
  participant O as ISP appliance
  P->>Z: Play title X · profile · device
  Z->>S: Authorise playback
  Note over S: entitlement · device capabilities · DRM
  S-->>P: Manifest · bitrate ladder · ranked appliance URLs
  P->>O: GET chunk 1 at 480p
  O-->>P: 2–4 s of video
  Note over P: pre-buffer ~5 s, then play · under 2 s
  loop every chunk
    P->>O: Next chunk at the rung ABR picked
    O-->>P: Chunk
  end
DiagramAppliance dies mid-stream: fail over from the manifest
%% title: Appliance dies mid-stream: fail over from the manifest
sequenceDiagram
  autonumber
  participant P as Player
  participant O as ISP appliance
  participant X as IXP appliance
  P->>O: GET chunk 41
  O--xP: timeout
  Note over P: no new API call · next URL is already in the manifest
  P->>X: GET chunk 41 (next in ranked list)
  X-->>P: Chunk 41
  alt buffer still healthy
    Note over P: keeps quality, viewer sees nothing
  else buffer below 5 s
    Note over P: ABR drops a rung · brief quality dip, no freeze
  end
DiagramRecommendations fail: the homepage degrades, not breaks
%% title: Recommendations fail: the homepage degrades, not breaks
sequenceDiagram
  autonumber
  participant C as Client
  participant R as Reco service
  participant M as ML models
  C->>R: Homepage rows for profile
  R->>M: Personalised rows
  M--xR: error (3rd in a row)
  Note over R: breaker OPEN · stop calling ML
  R-->>C: Popular titles (fallback)
  alt after the timeout · HALF_OPEN
    R->>M: Trial call
    M-->>R: ok · closes after enough successes
  else trial fails
    Note over R: back to OPEN · timeout restarts
  end

Data model#

DiagramCore entities
%% title: Core entities
classDiagram
  class Title {
    +titleId : string
    +runtime : minutes
    +genres : list
    +maturityRating : string
  }
  class Encode {
    +resolution : 240p to 4K HDR
    +bitrate : kbps · per-title ladder
    +codec : string
  }
  class Chunk {
    +index : int
    +duration : 2 to 4 s
    +url : string
  }
  class Profile {
    +profileId : string
    +accountId : string
    +parentalLevel : string
  }
  class ViewingRecord {
    +profileId : string
    +titleId : string
    +resumeAt : seconds · Continue Watching
    +watchedAt : timestamp
  }
  class Appliance {
    +ocaId : string
    +tier : ISP or IXP
    +capacity : up to 120 TB
    +cachedTitles : set
  }
  Title "1" --> "many" Encode : ~30 versions
  Encode "1" --> "many" Chunk : aligned boundaries
  Profile "1" --> "many" ViewingRecord : history
  ViewingRecord "many" --> "1" Title : of
  Appliance "many" --> "many" Encode : holds copies

Lifecycle#

DiagramPlayback session state machine
%% title: Playback session state machine
stateDiagram-v2
  [*] --> REQUESTED
  REQUESTED --> DENIED: not entitled
  REQUESTED --> AUTHORIZED: manifest issued
  AUTHORIZED --> PREBUFFERING: fetch first chunks at 480p
  PREBUFFERING --> PLAYING: ~5 s buffered
  PLAYING --> PANIC_LOW: buffer below 5 s
  PANIC_LOW --> PLAYING: buffer refilled
  PLAYING --> FAILING_OVER: appliance unreachable
  FAILING_OVER --> PLAYING: next appliance in list
  PLAYING --> REBUFFERING: buffer empty
  REBUFFERING --> PLAYING: chunk arrives
  REBUFFERING --> ABANDONED: viewer quits
  PLAYING --> ENDED: resume point saved
  ENDED --> [*]
  DENIED --> [*]
  ABANDONED --> [*]
  class ENDED ok
  class DENIED,ABANDONED bad
  class PANIC_LOW,FAILING_OVER,REBUFFERING queue

Decisions#

Decision Chose Over Because
Split Control plane on AWS, data plane on Open Connect One platform consistency for metadata, raw throughput near viewers for video
Delivery Own appliances inside ISPs Third-party CDN $0.02–0.05 / GB list price ≈ $7–18B a year
Cache fill Proactive off-peak fill of predicted hits Fill on demand no cold misses at peak, links busy only when idle
Placement Top 20 % on every server, long tail hashed once per region Everything everywhere hot load spreads, the tail still stays off the origin
Encoding Per-title ladder (VMAF) One fixed ladder up to ~20 % less bandwidth at the same quality
Quality Client-side ABR per 2–4 s chunk Fixed bitrate a few seconds of lower quality instead of a freeze
Dependencies Circuit breaker + fallback Keep retrying homepage shows popular titles, the sick service gets room

When it breaks#

Failure What users see Contain it with
ISP appliance goes offline brief quality dip next appliance in the manifest's ranked list, often IXP
Network drops (subway, tunnel) lower quality for a while ABR drops to the lowest rung below 5 s buffer
Recommendation service fails generic popular rows breaker opens, fallback, half-open probes
AWS region outage can't browse or start for a moment multi-region failover, cached recs, Chaos Kong drills
Midnight release herd slow starts, appliance overload pre-position on all appliances, pre-compute homepages, stagger by region
Live event, every new segment herd on each segment request coalescing at every tier, cap the top bitrate

Say it in the interview#