Netflix Architecture Deep Dive
A deeper look at each architectural layer of a global video-streaming platform — from the encoding pipeline through object storage, CDN edge architecture, adaptive bitrate protocol, and multi-region control-plane design.
Encoding Pipeline
The encoding pipeline transforms one master video file into dozens of streamable representations.
A studio upload triggers a job in an encoding queue (Kafka-like). Multiple workers pick up jobs in parallel — one per target resolution. Each worker transcodes the video using hardware-accelerated codecs (H.264, H.265/HEVC, AV1), then segments the output into 2-4 second chunks and writes them to object storage alongside a manifest file.
Codec selection
H.264 offers universal device compatibility. H.265 often achieves similar quality at a 30-50% lower bitrate (depending on content and encoder) but requires decoder support. AV1 is royalty-free and highly efficient but computationally expensive to encode. A production pipeline often maintains multiple codec variants.
Chunked segmentation
Each rendition is divided into 2-4 second segments. Shorter segments mean faster quality switching and lower startup latency. Longer segments mean less HTTP overhead and better CDN efficiency. Segment durations commonly range from about 2 to 10 seconds depending on the protocol and latency goals; 2-4 seconds is a common choice.
Per-Title Encoding
A single fixed bitrate ladder — the same resolution/bitrate combinations for every title — is a blunt instrument. An action movie with fast motion, frequent cuts, and complex textures needs more bits per pixel to look clean at a given resolution than a static dialogue scene or an animated title with flat color fields. Encode both at the same fixed ladder and one of two things happens: the complex title looks visibly worse than it needs to at that bitrate, or the simple title wastes bandwidth encoding detail nobody can perceive.
Per-title encoding fixes this by analyzing each title's complexity before choosing its ladder: a short pre-pass measures how much detail and motion the content actually has, and the encoder picks resolution/bitrate pairs optimized for that specific title rather than a one-size-fits-all default. Per-shot (or per-scene) encoding takes this further — the same title can have wildly different complexity from scene to scene (a quiet interior conversation versus an explosion-heavy action sequence), so encoding at finer granularity within a single title captures savings a per-title-only pass would miss.
- 01Encoding is async and horizontally parallelized across workers
- 02Each resolution/codec combination is a separate encoding job
- 03Segments are 2-4 seconds — independently cacheable by CDN
- 04The manifest is the only file the player needs to discover the full stream
Object Storage (Origin)
Object storage is the authoritative source for all encoded video content — the origin that CDN edges fill from.
Object storage (S3-like systems) is designed for high-durability, high-throughput reads of arbitrary binary objects. It replicates data across multiple availability zones automatically. It has no practical storage limit. It is dramatically cheaper per gigabyte than block storage.
For a streaming platform, object storage serves two roles: (1) durable archive of all content, and (2) CDN origin. On a cache miss, the CDN fetches the segment from object storage over a fast data-center network link. This origin-to-edge traffic is much smaller than edge-to-user traffic and stays within controlled infrastructure.
CDN Architecture
The CDN is a globally distributed network of edge nodes that cache content as close to users as physically possible.
CDN edges are co-located in Internet Exchange Points and ISP networks — sometimes literally in the same building as a user's ISP. Content cached there can be served at memory speed, with network latency measured in single-digit milliseconds.
Cache hierarchy
Large CDN networks use a multi-tier hierarchy: local edge nodes near users, regional parent nodes serving multiple local edges, and the origin as the final fallback. A cache miss at the local edge goes to the regional parent before going to origin. This reduces origin load further while keeping most requests within a regional network boundary.
Cache key
Each video segment URL is the cache key. Manifests may be cached with a short TTL to allow quality level updates. Segments are typically cached indefinitely — they are immutable once encoded.
Cache invalidation
For corrections or retractions, CDN edges support URL-based cache purge. Purge propagates to all edges within seconds. Segment immutability means invalidation is rare — only needed for content moderation or encoding errors.
Open Connect
Beyond using third-party CDN providers, Netflix operates much of its own purpose-built CDN hardware — Open Connect Appliances (OCAs) — rather than relying solely on external networks. There are two deployment models: OCAs can be embedded directly inside high-volume ISP networks (so a viewer's traffic never leaves their own ISP), or deployed at Internet Exchange Points, peering directly with many networks at once from a smaller number of physical locations.
Because upcoming popular content is known well in advance — release schedules aren't a surprise — it can be proactively pushed to appliances overnight, during low-traffic windows, rather than waiting for the reactive cache-fill-on-miss pattern that a general-purpose CDN relies on. By the time a title is available to stream, it's often already sitting on the appliance closest to the viewer, not fetched from origin on first request.
Adaptive Bitrate Protocol
HLS and DASH are the two industry-standard adaptive bitrate protocols. Both use text manifests and standard HTTP for segment delivery.
A master manifest lists all available renditions and their URLs. A media manifest (per rendition) lists every segment URL and duration. The player fetches the master manifest first, selects an initial rendition, then fetches segments continuously — switching renditions at segment boundaries based on measured throughput.
Startup quality selection
On startup, the player picks a conservative initial quality to minimize startup latency — it would rather start at 480p and ramp up than buffer for 3 seconds waiting to download a 4K segment. Fast startup is always the priority.
Buffer management
The player maintains a buffer of pre-downloaded segments (typically 15-30s). The ABR algorithm monitors buffer level: if the buffer is healthy, it can try higher quality; if buffer is draining, it switches down. The goal is never to let the buffer run empty.
- 01HLS and DASH use standard HTTP — CDN serves them without any special streaming support
- 02The player, not the server, decides which quality to download next
- 03Startup quality is conservative; quality ramps up as bandwidth is established
- 04Buffer health is the key signal — empty buffer causes buffering spinner, the worst user experience
Control Plane Design
The control plane handles all user-facing application logic — auth, catalog, recommendations, and playback metadata.
The control plane is a horizontally-scaled microservice cluster. Auth verifies identity and session tokens. The catalog service reads content metadata from a database (show titles, descriptions, genres, artwork). The recommendation service personalizes catalog ordering for each user — see our full Recommendation System deep dive for how. The playback API generates signed manifest URLs, resolving which CDN PoP to direct the player to based on the user's location.
Control-plane services are latency-sensitive but not bandwidth-heavy. They scale independently from video delivery and live on separate infrastructure. A recommendation computation spike has no impact on CDN throughput, and a CDN traffic spike has no impact on catalog browsing.
Recommendation System
Complete Design lists recommendations as a requirement and as a control-plane service. This layer explains how that personalization works, and it lives entirely in the control plane: it never touches a video byte. This layer covers only Netflix-specific placement and freshness; the full retrieval, ranking and feature-store design is in the standalone Recommendation System design.
The Signal Pipeline
Two kinds of signal feed recommendations. Implicit signals — what a user actually watches, pauses on, finishes, rewatches, and when — require no extra effort from the user and are collected continuously just from normal viewing. Explicit signals — thumbs up/down, star ratings — are more directly informative when present, but most users never provide them. In practice, implicit signals dominate simply because they're the only signal available for the vast majority of users and titles.
Approaches, Compared
Collaborative filtering
"Users who watched what you watched also watched X." Strong once there's enough viewing history to find similar users or similar titles, but it has a cold-start problem: a brand-new user with no history has no signal to collaborate from, and a brand-new title has no viewing history to be recommended on the strength of.
Content-based filtering
Recommends based on the content's own attributes — genre, cast, themes, metadata — rather than what other users did. This works from the very first day a title or user exists (a title's metadata is known immediately), but produces weaker, more generic personalization than a system that has real behavioral signal to work with.
Embedding-based / deep-learning approaches
Modern systems learn dense vector embeddings for users and titles from viewing behavior, then retrieve nearest neighbors in that embedding space. This can capture patterns neither pure collaborative nor pure content-based filtering catches alone — for example, a user's specific mix of genres and viewing time-of-day patterns — at the cost of needing far more data and infrastructure to train and serve than either simpler approach.
The Cold-Start Problem
Two distinct cold-start problems, with two distinct mitigations. New users have no viewing history at all — a common mitigation is a short onboarding taste survey (pick a few titles or genres you like) to seed an initial profile before any real behavioral signal exists. New titles have no engagement history yet — here, content-based metadata (genre, cast, themes) fills the gap as a fallback until the title accumulates enough real viewing data for collaborative or embedding-based signal to take over.
Batch vs. Real-Time
Not every recommendation row on the home screen needs the same freshness, and treating them all identically wastes either compute or user-perceived relevance. "Because You Watched X" style rows can be recomputed in a nightly batch job — they're based on longer-term taste patterns that don't meaningfully change minute to minute. "Continue Watching," by contrast, needs to reflect the current session almost immediately — if a user just paused a title, it needs to appear near the top the next time they open the app, not tomorrow after the next batch run. This is a genuine production design decision, not just an algorithm choice: which rows can tolerate batch latency, and which need to be computed close to read time.
- 01Implicit signals (watches, pauses, completion) dominate in practice because most users never provide explicit ratings
- 02Collaborative filtering is strong once there's history but has a cold-start problem for new users and new titles
- 03Content-based filtering works from day one but personalizes more weakly
- 04Modern systems combine approaches with learned embeddings and nearest-neighbor retrieval
- 05Not every recommendation row needs the same freshness — batch for long-term taste, near-real-time for session state
- 06Recommendations live entirely in the control plane and never touch video bytes
Watch State Sync
"Maintain per-user watch state" is a stated functional requirement — pause on one device, resume on another. This section explains how it works.
The Problem
A user pauses a show on their phone during a commute, then opens the TV app at home expecting to resume from roughly the same spot. The resume position needs to be available essentially everywhere within seconds of being written — but critically, without requiring continuous connectivity between the two devices. The phone and the TV never talk to each other directly; they both talk to a shared store.
Where State Lives
Watch position is stored in a lightweight, low-latency key-value store, keyed by user and title. The player updates it periodically during playback on a heartbeat interval — every 10 to 30 seconds, say — rather than on every single second of playback. This is a deliberate trade-off: writing on every second would multiply write volume for no real benefit, since a resume point being off by a few seconds is imperceptible to the user, while a write every 10-30 seconds keeps the stored position close enough to correct without generating unnecessary load.
Conflict Handling
It's rare but possible for the same title to be watched on two devices at once — a phone left playing in one room while a TV starts the same show in another. Last-write-wins by timestamp is an entirely reasonable choice here: whichever device's heartbeat write lands most recently determines the stored resume position.
Why This Doesn't Need Push Infrastructure
Unlike Uber's continuous driver-location stream — which has to be pushed to riders in near real time because a rider is actively watching a map update — watch state only needs to be correct at read time. A device fetches the current position when the app opens or a specific title is selected, not via a persistent push channel watching for updates. Notice what this system does not need: no WebSocket connection, no server-initiated push, no continuous stream — just a fast read on demand.
- 01Watch state lives in a low-latency key-value store, keyed by user and title
- 02Playback position is written on a heartbeat interval (10-30s), not continuously
- 03Last-write-wins by timestamp is the right call here — the cost of a wrong resume point is trivial
- 04Contrast with Uber: the correct consistency model depends on the cost of being wrong, not a universal rule
- 05This system needs only a read-through fetch at read time, not push infrastructure