Library / Blogs
Netflix: What Happens When You Press Play?
This article is a chapter from my new book Explain the Cloud Like I'm 10 . The first releas...
By High Scalability engineers · High Scalability · Added 2026-10-12
All content belongs to High Scalability engineers / High Scalability. We only link to it and give credit. Report a problem
Learn this article
About 37 min left. Your work is saved as you go.
What you are about to study
High Scalability wrote this to explain how they thought about a problem. You should know the basics: caching, queues and replication.
Ideas you will meet
- Distributed Systems
- Consensus, time, failure and the fundamentals of scale-out.
What we already know about this
Our own lessons on these ideas. Read them here before you start, so it makes sense.
Big Data and Cloud Data Platforms · 12 minBatch and stream processingMapReduce and Spark for large batch jobs, and streaming concepts: event time, windows, watermarks and exactly-once results.Read here
Two ways to process data
- Batch: process a bounded dataset (yesterday's logs) as a job that starts, runs and finishes. High throughput, results later.
- Stream: process an unbounded flow of events continuously as they arrive. Low latency, harder to get right.
Most platforms need both: stream for fresh insight, batch for heavy recomputation and history.
Before: batch: a big job on a schedule
100%After: stream: process each event
100%What changed
- Results arrive in seconds instead of hours
- Late and duplicate events must be handled
- Batch stays useful for reprocessing history
Batch: the MapReduce idea
Word count is the classic example.
100%Figure SDA-BDP-02-1 · MapReduce word count flow · © forcsguy.com
- Map: each worker reads a slice and emits key-value pairs (
("system", 1)). - Shuffle: the framework groups all pairs with the same key and sends them to the same reducer. This is the expensive step (network and sorting).
- Reduce: each reducer combines the values for its keys (
("system", 4812)).
Failures are handled by re-running tasks, which is possible because inputs are immutable and tasks have no side effects.
Spark improved this model: it keeps intermediate data in memory, expresses jobs as chains of transformations on DataFrames (with a query optimiser), and offers SQL, machine learning and streaming APIs on one engine. Today you usually write Spark or SQL, not raw MapReduce.
Image: Unknown authorUnknown author · Public domain · Source · Wikimedia Commons: Ford assembly line - 1913Stream processing
A stream processor reads events from a log (such as Kafka), transforms them, and writes results to another log, a database or a dashboard.
Common operations: filter and enrich, aggregate, join streams, and detect patterns.
Time is the hard part
- Processing time: when the system sees the event.
- Event time: when it actually happened.
Phones go offline, networks lag, and events arrive late and out of order. Computing "clicks per minute" by arrival time gives wrong answers. Use event time.
Windows
Aggregations need boundaries:
Window Meaning Tumbling Fixed, non-overlapping (every minute) Sliding Overlapping (last 5 minutes, updated each minute) Session Grouped by activity, closed by a gap of inactivity Watermarks and late data
A watermark is the system's estimate of "we have seen everything up to event time T". When it passes the end of a window, the window can close and emit a result. Choosing the delay trades latency against completeness. Events arriving after the watermark are late: drop them, send them to a side output, or update the earlier result.
State and failures
Windows and joins need state. Engines such as Flink keep state locally and checkpoint it periodically to durable storage, together with the position in the input log. After a failure they restore the checkpoint and replay from that position.
Delivery guarantees
- At-most-once: may lose events.
- At-least-once: may duplicate on replay.
- Exactly-once effect: achieved by replayable sources, checkpointed state and idempotent or transactional sinks, so a replay does not change results.
Architectures that combine both
- Lambda architecture: a batch layer computes accurate views from all data, a speed layer gives fast approximations; the two are merged. Powerful but means writing logic twice.
- Kappa architecture: treat everything as a stream. Keep the log long enough to replay history through the same code when logic changes. Simpler, if your log and engine can handle it.
- Modern engines and the dataflow model increasingly unify batch and streaming under one API.
100%Figure SDA-BDP-02-2 · Lambda and Kappa architectures · © forcsguy.com
Choosing
Need Choice Nightly reports, big joins, model training on history Batch (Spark, SQL warehouse) Fraud detection, live dashboards, alerting, real-time features Streaming (Flink, Kafka Streams, Spark Structured Streaming) Both with minimal duplication Streaming core with replayable log, or a unified engine Real-world reading
Related reading
- MapReduce: Simplified Data Processing on Large Clusters (paper)Dean and Ghemawat · GooglePapers
- Cape: Event Stream Processing Framework at DropboxDropbox engineers · DropboxCase Studies
- Pagelets Parallelize Server-side Processing at YelpYelp engineers · YelpCase Studies
- Optimizing CAL Report Hadoop MapReduce Jobs at eBayeBay engineers · eBayCase Studies
Show 6 moreShow fewer
- Bullet: Forward-Looking Query Engine for Streaming Data at YahooYahoo engineers · YahooCase Studies
- Samza: Stream Processing System for Latency Insighs at LinkedInLinkedIn engineers · LinkedInCase Studies
- Netflix: What Happens When You Press Play?High Scalability engineers · High ScalabilityBlogs
- CMU Database GroupCarnegie Mellon UniversityYouTube
- Omid: Transaction Processing Platform at YahooYahoo engineers · YahooCase Studies
- Big Data Processing at UberUberPapers
Low-Level Design Practice · 11 minChess gameBoard, pieces and rules: polymorphic pieces that generate moves, validating turns and check, and keeping the board model separate from the UI.Read here
The problem
Two players take turns on an 8 by 8 board. The system validates moves, detects check, checkmate and stalemate, and records the game.
Entities
100%Figure SDA-LLD-12-1 · Chess classes · © forcsguy.com
Inheritance is justified here: each piece type is a real kind of piece with its own movement rule.
Pieces know their own movement
abstract class Piece { constructor(readonly color: "W" | "B") {} abstract legalMoves(board: Board, from: Pos): Pos[]; // ignoring check } class Rook extends Piece { legalMoves(board: Board, from: Pos): Pos[] { return slide(board, from, [[1,0],[-1,0],[0,1],[0,-1]], this.color); // along rank and file until blocked } } class Knight extends Piece { legalMoves(board: Board, from: Pos): Pos[] { return [[1,2],[2,1],[-1,2],[-2,1],[1,-2],[2,-1],[-1,-2],[-2,-1]] .map(([dx, dy]) => ({ x: from.x + dx, y: from.y + dy })) .filter((p) => board.inside(p) && board.pieceAt(p)?.color !== this.color); } }A helper
slideis shared by rook, bishop and queen so the logic is not repeated.Validating a move
100%Figure SDA-LLD-12-2 · Validating a move · © forcsguy.com
Game status: check if the opponent's king is attacked; checkmate if in check with no legal move; stalemate if not in check but no legal move.
Moves as objects
class Move { constructor(readonly from: Pos, readonly to: Pos, readonly captured?: Piece, readonly kind: "normal" | "castle" | "enPassant" | "promotion" = "normal") {} } class History { done: Move[] = []; undone: Move[] = []; play(m: Move, b: Board) { b.apply(m); this.done.push(m); this.undone = []; } undo(b: Board) { const m = this.done.pop(); if (m) { b.revert(m); this.undone.push(m); } } }A move object makes undo, redo, history and notation straightforward: this is the Command pattern.
Design notes
- Special rules: castling (neither piece has moved, path clear and not attacked), en passant (needs the previous move), promotion (choose a piece). Each needs a little extra state:
hasMovedon pieces, last move on the game. - Model and view stay separate; an AI or network player implements the same
Playerinterface. - Clocks are a separate component observing the turn.
- Extensions: a move-suggestion engine, saved games, variants with different boards, online play with a server validating every move (never trust the client).
Real-world reading
Related reading
- Operating Systems: Three Easy PiecesRemzi and Andrea Arpaci-Dusseau · University of WisconsinBooks
- Ambry: Distributed Immutable Object Store at LinkedInLinkedIn engineers · LinkedInCase Studies
- Cloud Object Store at YahooYahoo engineers · YahooCase Studies
- Netflix: What Happens When You Press Play?High Scalability engineers · High ScalabilityBlogs
Show 6 moreShow fewer
- 8 Things You Need to Know Before a System Design InterviewGainlo engineers · GainloBlogs
- The Dataflow Model (paper)Akidau et al. · GooglePapers
- Atomic Object Engineering BlogAtomic Object engineers · Atomic ObjectBlogs
- Cloud Bouncer: Distributed Rate Limiting at YahooYahoo engineers · YahooCase Studies
- Object StorageDatacenterknowledge engineers · DatacenterknowledgeCase Studies
- Remind Engineering BlogRemind engineers · RemindBlogs
- Special rules: castling (neither piece has moved, path clear and not attacked), en passant (needs the previous move), promotion (choose a piece). Each needs a little extra state:
Low-Level Design Practice · 10 minVideo catalogue (Netflix-style)Titles, profiles, playback and recommendations: modelling content, per-profile state and a swappable recommendation strategy.Read here
The problem
Subscribers have accounts with several profiles. They browse a catalogue of movies and series, play titles, resume where they stopped, and see recommendations. This lesson models the domain. The streaming infrastructure (transcoding, CDN) is in the video-streaming lesson of the classic designs course.
Entities
100%Figure SDA-LLD-16-1 · Video catalogue classes · © forcsguy.com
A playable unit is a movie or an episode; the player only needs an asset id and a duration.
Playback and resume
100%Figure SDA-LLD-16-2 · Playback state · © forcsguy.com
class Player { state: "STOPPED" | "PLAYING" | "PAUSED" | "FINISHED" = "STOPPED"; constructor(private profile: Profile, private progress: ProgressStore) {} play(unit: Playable) { if (!canPlay(this.profile, unit)) throw new Error("not allowed"); // rating and plan rules, one place this.state = "PLAYING"; this.seek(this.progress.get(this.profile.id, unit.id) ?? 0); } tick(unit: Playable, pos: number) { this.progress.save(this.profile.id, unit.id, pos); // every few seconds, not every frame if (pos >= unit.duration * 0.95) this.state = "FINISHED"; } }Recommendations as a strategy
interface Recommender { forProfile(p: Profile, n: number): Title[] } const popularInGenre: Recommender = { forProfile: (p, n) => catalog.byGenres(topGenresOf(p)).filter(t => !watched(p, t) && allowed(p, t)).sort(byPopularity).slice(0, n), };Start with a simple strategy (popular in the genres you watch, not yet seen, allowed for the profile). Replace it later with collaborative or learned models behind the same interface.
Design notes
- One rule for access:
canPlayandallowedcombine plan limits, region licensing, maturity rating and device limits, and are used everywhere. - Concurrent streams: the plan limits simultaneous streams; track active sessions and refuse extra ones with a clear message.
- Progress writes are frequent and approximate; buffer and save periodically, and let the latest write win.
- Catalogue changes (titles added or removed by region and date) are data, not code.
- Extensions: downloads, parental controls, ratings, search, and "because you watched" rows.
Real-world reading
Related reading
- ByteByteGo: System Design Video SeriesAlex Xu · ByteByteGoYouTube
- Performance Optimization on Image, Video, Page LoadGoogle engineers · GoogleCase Studies
- Netflix: What Happens When You Press Play?High Scalability engineers · High ScalabilityBlogs
- SVE: Distributed Video Processing at Facebook Scale (paper)Huang et al. · Facebook ScalePapers
Show 6 moreShow fewer
- CS Video CoursesDeveloper-Y · GitHubGitHub
- Deterministic Aperture: A Distributed, Load Balancing Algorithm at TwitterTwitter engineers · TwitterCase Studies
- The Google File System (paper)Ghemawat, Gobioff and Leung · GooglePapers
- Aroma: Using ML for Code Recommendation at FacebookFacebook engineers · FacebookCase Studies
- Wealthfront Engineering BlogWealthfront engineers · WealthfrontBlogs
- Xero BlogXero engineers · XeroBlogs
- One rule for access:
Go deeper on this
A path through videos, articles, other case studies and code on the same ideas as Netflix: What Happens When You Press Play?.
Warm upGet the vocabulary first.
Books · Free from the author
Concurrent and Distributed Systems (Cambridge lecture notes)
Eight lectures on time, broadcast, replication, consensus and transactions, with notes, slides and video. Free from the author under CC BY-SA.
University of CambridgeIntermediate
Books · Free from the author
Computer Networks: A Systems Approach
How networks are built and why: protocols, routing, congestion control and the internet's architecture. The authors publish it free online under CC BY 4.0.
Systems ApproachIntermediate
WatchHow others solve the same problem, on video.
Videos belong to their creators and play from YouTube. More on YouTube (opens in a new tab)
ReadEngineers explain it in their own words.
Blogs · Free from the author · Read here
Scalable Web Architecture and Distributed Systems
A full chapter on the building blocks of large websites: availability, performance, reliability, scalability, caches, proxies, indexes, load balancers and queues. Free to read here under CC BY 3.0.
The Architecture of Open Source ApplicationsBeginner40 min
Papers · Read here
Facebook’s photo storage
This paper describes Haystack, an object storage system optimized for Facebook’s Photos application. Facebook currently stores over 260 billion images, which translates to over 20 petabytes of data.
USENIXIntermediate
See it in another companyThe same ideas, a different system.
Case Studies · Read here
Aroma: Using ML for Code Recommendation at Facebook
Thousands of engineers write the code to create our apps, which serve billions of people worldwide. This is no trivial task—our services have grown so diverse and complex that the codebase contains…
FacebookIntermediate
Case Studies · Read here
Brooklin: Distributed Service for Near Real-Time Data Streaming at LinkedIn
Brooklin—a distributed service for streaming data in near real-time and at scale—has been running in production at LinkedIn since 2016, powering thousands of data streams and over 2 trillion messages per day. Today, w...
LinkedInIntermediate
Read the codeSee how it looks when it is real.
GitHub
Engineering Blogs
A huge directory of company engineering blogs to learn from real production systems.
kilimchoiIntermediate
GitHub
Awesome Scalability
Curated reading list of articles on the architecture of scalable, reliable systems.
binhnguyennusIntermediate
Keep learning
Loading community…