Home › High-Level Design › Design Netflix
D

Design Netflix

Upload a movie once, encode it into dozens of formats, and stream it smoothly to 300 million people on phones, TVs, and laptops. It reads like a web app and then turns into a physics problem. The candidates who pass figure out in the first five minutes that this is really two systems glued together, and spend their time on the one that is actually hard.

High-Level DesignHard14 min read

If you remember five things

The whole answer in one glance. Everything below is the defense of these five calls.

  1. Split the planes. Control plane serves JSON, data plane serves video bytes, and they meet only at a signed manifest. This one split is the entire design.
  2. Video rides a custom CDN, never the origin. 150 Tbps of playback at peak cannot come from any data center, so you push bytes to the edge and the client talks straight to it.
  3. Chunked, parallel, idempotent transcoding. Split the master on keyframe boundaries, encode every chunk of every rendition in parallel, mark the title live only when all of them validate.
  4. The client picks quality, not the server. Adaptive bitrate against a short-lived signed manifest keeps the edge a dumb byte cache with zero per-user logic.
  5. Buffer the heartbeat writes. 1M progress updates per second land in Redis and flush to Cassandra every 30 seconds, trading a few seconds of accuracy for a 10x cut in durable writes.

1Clarifying the requirements#

Do not start drawing boxes. A streaming service is three products wearing one logo, and picking the wrong one to deep-dive fails the loop no matter how good the design is. So I scope hard first.

Candidate: Are we designing the whole thing, or should I focus somewhere? The video delivery path, the recommendation system, and the billing system are basically three separate products. Interviewer: Good instinct. Spend most of your time on video ingestion and playback delivery. Treat recommendations as a service you integrate with, not something you build from scratch today. Candidate: Do I own the CDN, or am I renting one? Interviewer: Assume you run your own edge caches. That is a real part of how a service at this scale actually works, and I want to see how you think about it. Candidate: Live streaming or just on-demand? They have different problems. Live has a hard latency budget and no time to pre-encode. On-demand I can encode once at leisure and cache forever. Interviewer: On-demand only. Pre-recorded catalog. Candidate: Last one. What is my success metric? If this were my service I would be judged on rebuffer ratio and play-start time, not QPS. Can I design against those? Interviewer: Yes. Assume start-to-play under two seconds and near-zero rebuffering are the bar.

What those answers just told me:

  • The interview is about ingestion and playback delivery, not billing or a ranker.
  • I run my own edge caches, so the CDN is mine to design, not a vendor I wave at.
  • On-demand only means I can encode once at leisure and cache the result forever.
  • Success is measured in rebuffer ratio and play-start latency, not raw QPS. That reframes the whole design.

Functional requirements

  • Browse and search a catalog, see a details page, and play any title.
  • Playback adapts to network quality (adaptive bitrate), resumes where you left off, and supports multiple audio and subtitle tracks.
  • Content owners upload a master file; the system transcodes it into many renditions automatically.
  • A home page with personalized rows (we integrate a recommendation service).
  • Track viewing history and "continue watching."

Non-functional requirements

  • Startup latency under about 2 seconds for play, and almost zero rebuffering once playing.
  • Available globally, read-heavy, and a regional outage must not take down playback.
  • Durable storage of masters. Losing a master costs real money to re-create, so that is unacceptable.
  • Scale to 300M subscribers, tens of millions watching concurrently at peak.

Explicitly out of scope (I say these out loud so nobody thinks I forgot):

  • Billing and payments.
  • The recommendation model itself. I consume its output, I do not build a ranker today.
  • Live events and ad insertion.
From the interviewer's chair

This opening is scored before you draw a single box. I am listening for whether you separate the video bytes from the JSON on your own, and whether you ask what you are optimizing for. A candidate who designs against rebuffer ratio and play-start time is already thinking like someone who has operated this. A candidate who opens with QPS and CRUD endpoints has told me they have not.

2Back-of-the-envelope estimation#

Get the scale in your head, because it decides the architecture. One number drives everything here, and I will flag it the moment I reach it.

The point of this section

You are not here to compute storage to three decimals. You are here to surface one load-bearing number: peak playback bandwidth is so large that no origin can serve it. That single figure is what forces a custom CDN and splits the whole design in two. Find it fast, then move on.

Users and concurrency.

  • 300M subscribers, say 200M daily active.
  • At evening peak maybe 15% are watching at the same time, so about 30M concurrent streams.
  • That 15% is a guess, but even off by 2x the conclusion does not change, so I will not agonize over it.

Playback bandwidth (this is the one that matters).

  • Average stream at 1080p is roughly 5 Mbps.
  • Some 4K at 15 to 25 Mbps, some phones at 1 Mbps, call it 5 Mbps blended.
30M concurrent x 5 Mbps = 150,000,000 Mbps
= 150 Tbps (terabits per second) at peak

150 Tbps. This is the number that drives the entire design.

  • No single region does hundreds of terabits. The fattest data-center uplinks top out in the low tens of Tbps.
  • This has to be pushed to the edge, close to users, which is the entire reason a custom CDN exists.
  • Everything else in this interview is a consequence of this line.
150 Tbps
The number that decides everythingPeak playback bandwidth across 30M concurrent streams. It is why video cannot touch an origin, why the client talks straight to the edge, and why pre-positioning and cache hit rate are load-bearing, not nice-to-haves. Remember this one; it comes back in every trade-off.

Control-plane QPS (large but ordinary).

  • Say each active user makes 1 API call every 20 seconds while browsing, plus a playback heartbeat every 30s.
30M concurrent x (1 heartbeat / 30s) = ~1M heartbeats/sec
browsing + home + search peaks ~ a few hundred K QPS
  • So on the order of 1 to 2M QPS of small requests. Sharded services and caches handle it.
  • The gap between the two numbers is the whole story: 150 Tbps of video versus 1 to 2M QPS of JSON. One is physics, the other is a normal web backend. I will not spend them equally.

Storage.

  • Catalog of 20,000 titles, 2 hours each.
  • Masters are huge: a ProRes-ish master for a 2-hour film runs 1 to 2 TB. Renditions add 20 to 40 GB.
Masters:    20,000 x 1.5 TB  = 30 PB
Renditions: 20,000 x 30 GB   = 0.6 PB  (small! this is what we actually serve)
  • Masters dominate storage (cold, durable, cheap tier). The hot serving set, the renditions, is under a petabyte and highly cacheable.
  • A long tail helps: a few thousand titles are 90% of watch time, so the working set an edge must hold is tens of terabytes, which fits on commodity SSD at every edge location.

Egress cost sanity check.

  • 150 Tbps sustained would bankrupt you at public-cloud egress rates.
  • That is a second, independent reason to own the CDN and peer directly with ISPs rather than pay per gigabyte out of a cloud region.
  • At staff level the cost model is part of the design, not an afterthought.

3Core APIs#

Keep the control plane small and boring on purpose. Clean REST over HTTPS is a feature.

GET /v1/home?profileId=abc&page=0
  200 -> { rows: [ { title, type, items:[{titleId, art}] } ] }

GET /v1/titles/{titleId}
  200 -> { titleId, name, synopsis, runtime, maturity, availableRenditions }

GET /v1/search?q=heist&profileId=abc
  200 -> { results:[{titleId, name, score}] }

POST /v1/playback/license
  body: { titleId, profileId, deviceCaps:{codecs, maxRes, drm} }
  200 -> { manifestUrl, drmLicenseUrl, sessionId, expiresAt }

POST /v1/playback/heartbeat
  body: { sessionId, positionMs, bitrate, bufferMs }
  204

PUT  /v1/profiles/{profileId}/progress
  body: { titleId, positionMs }
  204

The load-bearing endpoint is POST /v1/playback/license.

  • It turns "I want to watch" into "here is a signed manifest and a DRM license."
  • It does authorization, device capability matching, and picks which CDN edge to point you at.
  • Everything after it is the player talking to the CDN directly, not to us.

Two choices in that endpoint I would defend.

  • manifestUrl is signed and short-lived (expiresAt is minutes out, not hours), so a leaked URL dies fast.
  • deviceCaps comes from the client, not a server lookup, because the same account plays on a 4K TV and a 720p phone in the same hour. Capability lives with the device, entitlement with the account, and the license step returns only the intersection.

4High-level design#

The point of this section

The box diagram is table stakes. What earns points is one seam: the client arrow goes straight to the edge, not through the gateway. Put video through your API tier and 150 Tbps lands on your servers and the design is dead on arrival. Draw the boxes fast, then defend that one arrow.

I split the system hard down the middle:

  • Control plane serves JSON and is a normal microservice stack.
  • Data plane serves video bytes and is a CDN.
  • They meet only at the manifest. This split is the single most important diagram in the interview, so I draw it first and keep pointing back at it.
flowchart TD C[Client Player] --> GW[API Gateway] GW --> HOME[Home Service] GW --> SRCH[Search Service] GW --> PLAY[Playback Service] HOME --> REC[Recommendation Service] HOME --> CACHE[(Redis Cache)] SRCH --> IDX[(Search Index)] PLAY --> META[(Catalog DB)] PLAY --> DRM[DRM License Service] PLAY --> STEER[Edge Steering] C --> EDGE[(CDN Edge Cache)] EDGE --> ORIGIN[(Rendition Origin)]
The control plane and data plane side by side. The arrow from the client straight to the CDN edge, bypassing the entire gateway stack, is the whole trick. If it went through the gateway, 150 Tbps would hit your servers.

The upload and encoding side is a separate pipeline that feeds the origin:

flowchart LR UP[Content Upload] --> RAW[(Master Storage)] RAW --> ORCH[Transcode Orchestrator] ORCH --> Q[Encode Job Queue] Q --> W[Encoder Workers] W --> PKG[Packager and DRM] PKG --> ORIGIN[(Rendition Origin)] ORIGIN --> FILL[Edge Fill] FILL --> EDGE[(CDN Edge Cache)]
The ingestion pipeline. A master is transcoded into renditions offline and written to the origin, then filled out to edge caches. None of this is in the playback hot path.

How a play actually happens, start to finish.

  • The player hits the Playback Service for a license.
  • We check the subscription, match the device's codec and resolution support, and generate a signed manifest listing the renditions and their segment URLs.
  • We hand back a DRM license and steer the player to the best edge for its location.
  • The player fetches a manifest from that edge and starts pulling 2-to-6-second segments, stepping bitrate up or down as its buffer fills.
  • We never touch those segment requests. The expensive part is handled by caches near the user.

Sortable, time-ordered IDs for titles and renditions are UUIDs here, not snowflakes, because nothing in this system paginates by time the way a social feed does. The access patterns are "fetch this title" and "fetch this profile's progress," both key lookups.

5Data model#

Use a few stores, each picked for its access pattern. Catalog metadata and write-heavy progress are different beasts, so I do not force them into one database.

Catalog metadata is relational-ish and small, so Postgres with read replicas is fine. Progress and heartbeats are write-heavy, so they go in a wide-column store like Cassandra, partitioned by profile.

titles (Postgres)

field type notes
title_id uuid PK
name text indexed for search feed
synopsis text
runtime_ms bigint
maturity text rating for parental controls
release_year int
status text draft, encoding, live, pulled

renditions (Postgres) one row per encoded variant of a title

field type notes
rendition_id uuid PK
title_id uuid FK to titles
codec text h264, hevc, av1
resolution text 480p 720p 1080p 4k
bitrate_kbps int
drm_scheme text widevine, fairplay, playready
segment_base_url text path on origin

watch_progress (Cassandra) partition key = profile_id

field type notes
profile_id uuid partition key
title_id uuid clustering key
position_ms bigint last known position
updated_at timestamp last write wins
completed boolean drives continue-watching filter

Why progress gets its own store.

  • It is the highest write volume in the system: a position update every few seconds per stream.
  • It needs no transactions, and last-write-wins is exactly the right conflict rule.
  • Jamming it into the catalog Postgres would be the fastest way to melt it.

Two schema details that earn points.

  • The status field on titles with a pulled state. When legal makes us pull a title, I flip status to pulled and the Playback Service refuses new licenses for it within one read. That makes "a pulled title must stop playing" strongly consistent, not something I hope the cache eventually learns.
  • The partition key on watch_progress is profile_id, not account_id. A household has multiple profiles, each with its own continue-watching row, and partitioning by profile keeps every read a single-partition lookup.

6Deep dives#

6.1 The transcoding pipeline: never encode a 2-hour file as one job#

This is the first deep dive because a naive encode quietly sinks the whole ingestion story.

  • A master film can be 1 to 2 TB.
  • One worker encoding the whole thing into one rendition is hours of wall-clock time, times 8 renditions times 3 codecs.
  • A single crash wastes the whole run. Unacceptable.

The move is to split the master into chunks.

  • Cut it into 2-to-5-minute GOP-aligned segments.
  • Encode every chunk of every rendition in parallel across a big fleet, then stitch and package.
  • A 2-hour film becomes about 30 chunks x 24 rendition-codec combos, roughly 700 independent jobs that run at once.
  • What took hours becomes minutes, and a failed chunk re-runs on its own.

Why GOP-aligned matters.

  • A video segment has to start on a keyframe (an I-frame) or the decoder has no reference to build the first frames from.
  • Split mid-GOP and the stitched output glitches at every chunk boundary.
  • So the orchestrator splits on keyframe boundaries, which is also exactly where the player later cuts segments for adaptive bitrate.
  • The chunk boundaries and the playback segment boundaries are the same boundaries. That alignment is not an accident.
sequenceDiagram participant O as Orchestrator participant Q as Job Queue participant W as Worker Fleet participant P as Packager participant R as Rendition Origin O->>O: split master into chunks O->>Q: enqueue chunk x rendition jobs Q->>W: pull job W->>W: encode one chunk one rendition W->>P: upload encoded chunk P->>P: validate and stitch per rendition P->>R: write segments plus manifest R-->>O: mark title live
The transcode pipeline. Thousands of chunk-by-rendition jobs run in parallel, each validated before stitching, and the title is marked live only after every required chunk has passed.

Two things I will not skip.

  • Validation. A silently corrupt chunk that passes to live means every viewer sees a glitch at minute 42. Each chunk gets checksummed and spot-decoded before stitching.
  • Idempotency. The queue redelivers, so a job keyed by (chunk_id, rendition_id) writing to a deterministic path means a duplicate run just overwrites the same bytes. No harm.

The commit point is "mark title live."

  • It is a single Postgres update that flips status to live.
  • It fires only after every chunk of every required rendition has validated.
  • Until then the title is invisible to playback, so a half-encoded film can never leak to a user.

6.2 Adaptive bitrate and why the player, not the server, decides quality#

The key insight here is that pushing the quality decision to the client is what keeps the edge dumb and cheap.

  • I serve each title as a manifest (think DASH or HLS) listing every rendition and the URL of every segment.
  • The player measures its own download speed and buffer level and picks the next segment's bitrate itself.
  • If your WiFi drops, the player quietly steps from 1080p to 480p at the next segment boundary and you never see a spinner. When it recovers, it steps back up.

How the player decides, concretely.

  • It keeps a buffer target, say 30 seconds of video, and watches two signals: how fast the last few segments downloaded, and how full the buffer is.
  • Buffer draining faster than it fills: the next segment request drops to a lower bitrate.
  • Buffer comfortably full and downloads fast: it steps up.
  • Segments are 2 to 6 seconds, so the player gets a fresh decision every few seconds and reacts to a bad network inside one segment of lag.

This is deliberately server-dumb.

  • The edge cache has no idea what quality you are on. It serves whatever segment URL you ask for.
  • That is what makes the CDN layer cheap to scale: a pure byte cache with no per-user logic.
  • All the intelligence lives in the client and in the manifest we signed at license time.

Entitlement meets reality in the manifest.

  • The manifest is short-lived and signed. Copy a segment URL and it expires.
  • Ask for a resolution your account or device is not entitled to and that rendition was never in your manifest in the first place.
  • A basic plan gets a manifest that simply omits the 4K renditions, so there is nothing to enforce at serve time. The edge never has to know what plan you are on.
Pause before you read on: if the player, not the server, chooses the bitrate, what has to be true about the edge cache for this to scale to 150 Tbps?
Reveal the answer
The edge has to be a pure byte cache with zero per-user logic. It serves whatever segment URL it is handed and never computes anything. All the per-user intelligence (entitlement, device matching, quality) was baked into the signed manifest at license time, so the hot path is just "return these bytes." The moment the edge has to reason about a user, you cannot scale it to terabits.

6.3 The CDN: serving 150 Tbps without an origin meltdown#

You cannot serve 150 Tbps from any origin, so the design is a tiered cache pushed as close to users as possible, often inside ISP networks.

flowchart TD P1[Player in Mumbai] --> E1[(Local Edge ISP)] P2[Player in Pune] --> E1 E1 -->|miss| MID[(Regional Mid Tier)] MID -->|miss| ORIGIN[(Rendition Origin)] ORIGIN --> S3[(Master and Rendition Store)]
The tiered CDN. Most reads are served from an ISP-local edge; misses walk up to a regional mid-tier and only rarely to the origin. Fill traffic behind the edges is a tiny fraction of what the edges serve.

The economics work because of the long tail.

  • A few thousand popular titles are 90% or more of watch time.
  • Those renditions get pre-positioned onto edge caches before demand hits, especially a big release we know drops Friday.
  • We literally push the bytes out overnight so Friday's spike is already cached everywhere.
  • Cold, obscure titles accept a slower first play (one trip to origin) and then they are warm too.

Edge steering is the other half.

  • When the Playback Service hands you a manifest, it also picks which edge cluster to send you to, based on geography, which caches are healthy, which already hold this title, and current load.
  • If an edge gets hot or fails, we steer new sessions elsewhere.
  • Existing players re-resolve the host periodically, so they drift over on their own.
  • That is how a single edge going down does not become 500,000 buffering spinners.

Put a number on the fill traffic.

  • Fill (edge pulling from mid-tier pulling from origin) is a tiny fraction of serve traffic once hit rates are high, maybe 1 to 2%.
  • At a 98% edge hit rate, origin sees 2% of 150 Tbps, about 3 Tbps, and the mid-tier soaks up most of that again, so true origin load is a rounding error.
  • The entire design lives or dies on that hit rate. That is why pre-positioning and the long tail are load-bearing, not nice-to-haves.

6.4 Resume and the heartbeat write path#

"Continue watching" feels trivial and is quietly one of the heaviest write paths in the system.

  • At 30M concurrent streams emitting a heartbeat every 30 seconds, that is about 1M writes per second of position updates.
  • A naive design writes every one of them straight to Cassandra and melts it.

So I buffer.

  • The live position goes to Redis keyed by sessionId, updated on every heartbeat in memory.
  • A background flush writes the latest position to Cassandra every 30 seconds.
  • An explicit flush fires on pause, stop, or app-background.
  • If a server crashes between flushes, the worst case is the user resumes a few seconds early, which no human notices.

What this buys.

  • A roughly 10x cut in durable write volume, and it keeps write amplification off the store that also answers "what is on my continue-watching row" reads.
  • The heartbeat doubles as liveness and quality telemetry: bitrate and bufferMs in the payload feed the rebuffer-ratio metric I care about most.
Red flag that fails you here

Writing every one of those million heartbeats per second straight to the durable store, then looking surprised when I ask what happens to Cassandra. Buffer in memory and flush on an interval, and name what you lose on a crash (a few seconds of resume position, which nobody notices). Candidates who have not run a write-heavy path reach for the synchronous write every time.

7Bottlenecks and trade-offs#

Origin as a single point of pain.

  • Even at a 1 to 2% miss rate, a brand-new global release that is not pre-positioned could stampede the origin.
  • Defense: pre-position known hits, and use request coalescing at the mid-tier so 10,000 simultaneous misses for the same segment turn into one origin fetch, not 10,000.
  • Skip coalescing and a cold viral title knocks the origin over at launch, which is exactly when you least want it.

Heartbeat write storm.

  • A million progress writes per second is real, and I will not write each one to Cassandra synchronously.
  • Keep the latest position in Redis, flush to Cassandra every about 30s or on pause/stop.
  • Lose a few seconds of resume position on a crash and nobody cares. That trades a tiny bit of accuracy for a 10x cut in durable writes.

Thundering home page.

  • Every app open hits the home feed, and recommendations are expensive to compute live.
  • I precompute each profile's rows asynchronously and cache them, refreshed every few hours or on a signal like "finished a show."
  • The home endpoint becomes a cache read. The trade-off is staleness: your rows might be a few hours behind your latest binge, which for a browse screen is totally fine.

Consistency choice.

  • The catalog must be correct (a pulled title must stop playing), so that path is strongly consistent off Postgres.
  • Watch progress is eventually consistent, last-write-wins, which is right because two devices updating position just want the most recent one.
  • I am explicitly trading global consistency for availability and write throughput where it does not hurt.

DRM and device matrix.

  • Three DRM schemes, dozens of codec and resolution combinations across TVs, phones, and browsers.
  • The cost is a sprawling capability-matching step at license time and encoding more renditions than any single device needs.
  • The alternative, fewer renditions, means worse quality-per-bitrate and locked-out devices.
  • I pay the encoding cost because encoding is a one-time batch expense and playback quality is the product.

Observability and SLOs.

  • Watch three numbers first: rebuffer ratio (seconds buffering over seconds played), play-start latency p95, and edge cache hit rate per region.
  • Those tell you if the data plane is healthy long before a dashboard of CPU graphs does.
  • If rebuffer ratio climbs in one region, I look at that region's edge hit rate before anything else, because the two move together.

Where renting a CDN would have won.

  • For a small catalog with modest concurrency, a commercial CDN is simpler and cheaper, and I would skip building edge caches entirely.
  • I only pay to own the CDN because 150 Tbps at public-cloud egress rates would bankrupt the business and no vendor peering beats being inside the ISP.

Let the peak bandwidth number pick the architecture, not habit.

8Summary#

The decisions that matter:

  • Split the planes. Control plane (home, search, license, progress) is a standard sharded microservice stack with Postgres, Cassandra, Redis, and a search index. Data plane is a tiered CDN serving segments as a dumb byte cache, and it carries almost all the load.
  • Video rides a custom CDN, never the origin. 150 Tbps at peak cannot come from any data center, so the client talks straight to the edge and we only ever hand it a signed manifest.
  • Chunked, parallel, idempotent transcoding, so a 2-hour film encodes in minutes, not hours, and a half-encoded title can never leak to a user.
  • Client-driven adaptive bitrate against a short-lived signed manifest, so the edge needs no per-user logic and entitlement is enforced by what the manifest omits.
  • Buffered progress writes, so a million heartbeats per second become a Redis update plus a periodic flush, strong consistency reserved for the catalog.
  • Out of scope by choice: billing, the recommendation model, live events, ads. Naming them keeps me honest about what the session covered.
Follow-ups the interviewer will ask (and your answers)
"A title just dropped globally and it is not pre-positioned. The origin is about to get stampeded. Now what?"
Request coalescing at the mid-tier: 10,000 simultaneous misses for the same segment collapse into one origin fetch, and the rest wait on that in-flight pull. Combined with pre-positioning known hits overnight, the origin never sees more than a trickle. Coalescing is what keeps a cold viral title from knocking the origin over at launch.
"Legal makes you pull a title immediately. How do you guarantee it stops playing?"
The catalog path is strongly consistent off Postgres. I flip the title's status to pulled, and the Playback Service refuses to issue new licenses within one read. Existing manifests are short-lived and expire in minutes, so sessions die out fast. I do not rely on the cache eventually learning; the license step is the enforcement point.
"Why does the client pick the bitrate instead of the server choosing it for them?"
Because it keeps the edge a dumb byte cache. The player sees its own buffer and download speed first, reacts inside one segment of lag, and asks for whichever segment URL it wants. If the server chose quality, the edge would need per-user logic and you could not scale it to 150 Tbps. All per-user intelligence lives in the manifest we signed at license time.
"A million progress writes per second will melt Cassandra. How do you survive it?"
Buffer. The live position lives in Redis keyed by sessionId and updates on every heartbeat in memory; a background job flushes the latest value to Cassandra every 30 seconds, plus an explicit flush on pause, stop, or app-background. A crash between flushes costs a few seconds of resume position, which no one notices, and durable writes drop about 10x.
"Why split the master into 700 jobs instead of encoding it straight through?"
Speed and failure isolation. Encoding a 2-hour master straight into 8 renditions across 3 codecs is hours of wall-clock time, and one crash wastes the whole run. Splitting on keyframe boundaries into roughly 30 chunks times 24 rendition-codec combos gives about 700 independent jobs that run in parallel; a failed chunk re-runs alone, and the keyed deterministic output path makes a redelivered job idempotent.

What you can now explain in the room

  • Why a streaming service splits into a control plane and a data plane, and why they meet only at the manifest.
  • How to derive the one number that decides everything: 150 Tbps of playback versus 1 to 2M QPS of JSON.
  • Why video cannot pass through your servers, and how a tiered CDN with pre-positioning serves it instead.
  • How chunked, parallel, idempotent transcoding encodes a 2-hour film in minutes and never leaks a half-encoded title.
  • Why the client picks the bitrate, and how that keeps the edge a dumb byte cache that can scale to terabits.
  • Why heartbeat writes get buffered in Redis, and exactly what you lose on a crash.

For related walkthroughs, see our guides on Design YouTube, Design a CDN, and Design a Rate Limiter.

Get a prep plan built around your Design Netflix interview

Tell us the role and your interview date. We will send back a dated, day by day plan. Free.

Thanks. Check your inbox, your Design Netflix prep plan is on the way.