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- Control plane (AWS): small requests that must be correct. Data plane (Open Connect): huge, read-only bytes, the same for every viewer of a title.
- After the manifest, every video byte comes from an appliance in or next to the viewer's ISP; the cloud never streams video.
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"]:::serviceKey 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
endDiagramAppliance 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
endDiagramRecommendations 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
endData 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- Video lives in S3 (~20 GB a title, ~360 TB for one copy); appliances hold ~36 PB of copies. Users and viewing history in Cassandra, keyed by profile; billing in MySQL.
- Chunks of every rung start at the same timestamps, so the player can switch rung at any chunk.
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#
- "The cloud decides, the ISP delivers." AWS hands out a manifest; Open Connect sends 100 % of the video.
- "50 Tbps picks the architecture." 10M × 5 Mbps can't leave a few regions, so the bytes must start inside ISPs.
- Move bytes before anyone asks: off-peak fill of predicted hits keeps the edge at 90 %+ hits when everyone presses play.
- The player owns quality: chunks on shared boundaries plus ABR with 20 % headroom; drop fast, climb slowly.
- Egress = streams × bitrate: per-title encoding saves up to ~20 %, and capping the top rung is the lever in an emergency.
- Degrade, don't fail: every service call behind a breaker with a fallback; failover URLs are already in the manifest.
- Live breaks pre-positioning: segments are made as they are watched, so every tier must coalesce concurrent misses.