Library / Case Studies

A 360 Degree View of the Entire Netflix Stack - High Scalability -

This is a guest repost by Chris Ueland , creator of Scale Scale , with a creative hig...

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 case study

About 37 min left. Your work is saved as you go.

What you are about to study

High Scalability explains a real system. 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.

  • Software Design Essentials · 10 minStructural patterns: Adapter, Decorator, Facade, ProxyHow to compose objects and wrap existing code so pieces fit together, add behaviour and hide complexity.Read here

    The goal

    Structural patterns are about composing classes and objects into larger structures, often by wrapping existing ones, without changing them.

    Adapter

    Make an existing class fit the interface you need.

    // Your code expects this
    interface Gateway { charge(cents: number, token: string): Promise<{ ok: boolean }> }
    
    // A third-party library with a different API
    class AcmePay { makePayment(req: { amount: number; source: string }): Promise<{ status: string }> {/*...*/} }
    
    class AcmeAdapter implements Gateway {
      constructor(private acme: AcmePay) {}
      async charge(cents: number, token: string) {
        const r = await this.acme.makePayment({ amount: cents / 100, source: token });
        return { ok: r.status === "approved" };
      }
    }
    

    Use it to wrap third-party and legacy code, and to keep vendor details out of your core. Swapping providers then means writing one new adapter.

    Decorator

    Add behaviour by wrapping an object that has the same interface. Wrappers stack in any order.

    interface Weather { forecast(city: string): Promise<string> }
    
    class Logged implements Weather {
      constructor(private inner: Weather) {}
      async forecast(city: string) { console.time(city); const r = await this.inner.forecast(city); console.timeEnd(city); return r; }
    }
    class Cached implements Weather {
      private cache = new Map<string, string>();
      constructor(private inner: Weather) {}
      async forecast(city: string) {
        if (!this.cache.has(city)) this.cache.set(city, await this.inner.forecast(city));
        return this.cache.get(city)!;
      }
    }
    const service: Weather = new Logged(new Cached(new RealWeather()));
    

    Typical uses: logging, caching, retries, authentication, compression, metrics. HTTP middleware is this idea.

    Decorators stack like layers

    Figure SDA-SDE-04-1 · Wrapping a service with logging and caching · © forcsguy.com

    Facade

    A simple front over a complex subsystem.

    class VideoConverter {                       // the facade
      convert(file: string, format: "mp4" | "webm") {
        const audio = new AudioExtractor().extract(file);
        const frames = new FrameDecoder().decode(file);
        return new Encoder().encode(frames, audio, format);
      }
    }
    

    Callers use convert, not five classes. It reduces coupling and gives you a stable surface to keep when internals change. Do not let it become a "god object" that does everything.

    Proxy

    A stand-in with the same interface that controls access to the real object.

    KindPurpose
    Virtual proxyCreate or load the real object only when needed (lazy loading)
    Protection proxyCheck permissions before forwarding
    Remote proxyHide that the real object is on another machine (RPC stubs)
    Caching or logging proxyAdd cross-cutting behaviour

    The structure matches a decorator; the intent differs: control access versus add behaviour.

    Composite

    Treat individual objects and groups of them uniformly, usually as a tree.

    interface Node { size(): number }
    class File implements Node { constructor(private bytes: number) {} size() { return this.bytes; } }
    class Folder implements Node {
      constructor(private children: Node[]) {}
      size() { return this.children.reduce((sum, c) => sum + c.size(), 0); }
    }
    

    A caller asks any node for its size() without caring whether it is a file or a folder. Used for file systems, UI component trees and organisation charts.

    Bridge and Flyweight (briefly)

    • Bridge: split an abstraction from its implementation so each can vary independently. Example: shapes (circle, square) times renderers (screen, PDF), without a class for each combination.
    • Flyweight: share the common, unchanging part of many similar objects to save memory (for example one glyph shape reused for every occurrence of a letter).

    Choosing

    NeedPattern
    Make an incompatible API fitAdapter
    Add behaviour without editing or subclassingDecorator
    Simplify a complicated subsystemFacade
    Control, defer or guard accessProxy
    Treat part and whole alikeComposite

    All of them work by delegation: an object that holds another and forwards calls, adding something on the way.

    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 A 360 Degree View of the Entire Netflix Stack - High Scalability -.

  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…