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

Open original source

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

    After: stream: process each event

    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.

    Figure SDA-BDP-02-1 · MapReduce word count flow · © forcsguy.com

    1. Map: each worker reads a slice and emits key-value pairs (("system", 1)).
    2. 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).
    3. 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.

    A 1913 assembly line: work flows past stations continuously, the picture behind stream-processing pipelinesImage: Unknown authorUnknown author · Public domain · Source · Wikimedia Commons: Ford assembly line - 1913

    Stream 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:

    WindowMeaning
    TumblingFixed, non-overlapping (every minute)
    SlidingOverlapping (last 5 minutes, updated each minute)
    SessionGrouped 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.

    Figure SDA-BDP-02-2 · Lambda and Kappa architectures · © forcsguy.com

    Choosing

    NeedChoice
    Nightly reports, big joins, model training on historyBatch (Spark, SQL warehouse)
    Fraud detection, live dashboards, alerting, real-time featuresStreaming (Flink, Kafka Streams, Spark Structured Streaming)
    Both with minimal duplicationStreaming core with replayable log, or a unified engine

    Real-world reading

    Open this lesson with its quiz and exercise

  • 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

    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 slide is shared by rook, bishop and queen so the logic is not repeated.

    Validating a move

    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: hasMoved on pieces, last move on the game.
    • Model and view stay separate; an AI or network player implements the same Player interface.
    • 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

    Open this lesson with its quiz and exercise

  • 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

    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

    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: canPlay and allowed combine 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

    Open this lesson with its quiz and exercise

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?.

  1. Warm upGet the vocabulary first.

  2. 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)

  3. ReadEngineers explain it in their own words.

  4. See it in another companyThe same ideas, a different system.

  5. Read the codeSee how it looks when it is real.

Keep learning

Loading community…