System Design Masterclass · Module 26 / Week 4 · CAPSTONE

Design the Playback Path

The whole course, one system: a user in Riyadh presses play on a marquee live match, on a smart TV, at kickoff, alongside five million others. Walk every stage, name every decision, and cite the module that defends it. This is the design you should be able to conduct on a whiteboard from memory.

~4h exercise-drivenAll 25 modules applyInteractive walkthrough

No fast track here

The capstone is the assessment. Work every stage before expanding it — say your answer out loud, then compare. If a stage's reasoning feels thin, its module number is right there; go back before going on.

STEP 01

Press play → first frame → 90 minutes

MANDATORY

For each stage: before expanding, answer — what happens here, what are the load numbers, what breaks, and which defenses stand where?

DNS: GeoDNS/latency steering to the SA region, moderate TTLs on stable steering endpoints, failover designed below DNS; the TV's frozen resolver behavior assumed, not hoped about. Transport: TLS 1.3 (session resumption for this returning device — 1 RTT), HTTP/3 at the edge for the lossy living-room wifi; connections kept alive under the LB idle threshold. Numbers: at 5M concurrent, connection *establishment* at kickoff is itself a herd — edge capacity for handshake CPU, not just steady-state RPS.
M06M11M02
TV logged in long ago via device authorization grant (code on TV, approval on phone); holds a rotating refresh token + 10-min ES256 access token, validated locally at every service via JWKS — no auth-server call on the hot path. Claims carry plan tier and device class; the DRM security level and entitlement freshness do NOT ride as claims — they're checked live where they matter (S5), because a mid-session upgrade must take effect now. Gateway holds the small revocation denylist for the cases that can't wait a TTL.
M22M20M01
L4→L7 edge; gateway does token validation, per-device+app-version rate limits (the broken-firmware guard), priority tagging (playback-critical), and routes to the playback/session service — which takes the concurrent-streams slot: not a lock but an atomic Redis Lua check-and-incr with heartbeat-leased slots that self-free on crash. Fan-out from here runs on gRPC with propagated deadlines (~total budget 800 ms for session setup), P2C-balanced per-call, bulkheaded per dependency.
M08M09M14M19M07M13
Segments: immutable, max-age=31536000, immutable, multi-CDN with client-side QoE steering. Live manifest: TTL ≈ half segment duration + SWR + stale-if-error, origin shield + request collapsing at every layer — the kickoff manifest herd reaches origin as ~1 request. Init segments prewarmed to POPs per the event runbook. CDN tokens signed (HMAC) but excluded from the cache key. Target: ≥98% offload — which M25 identified as the platform's biggest cost lever, so this stage is also the CFO's favorite.
M10M01M20M25
CDM challenge → license service: token → entitlement decision from an event-invalidated cache (invalidation rides the outbox — never TTL-only, because TTL staleness here is the 428 storm), device attestation → per-tier keys (UHD keys exist only for L1 devices — the studio matrix enforced cryptographically). License prefetch allowed pre-kickoff to flatten the herd; per-session licenses idempotent; the DRM/HSM edge breakered with a pre-signed fail-open-bounded policy for non-premium content. Error taxonomy distinct: not-entitled ≠ not-capable ≠ transient.
M23M01M18M16M13
The purchase that made S5 say yes: an orchestrated saga (order → payment pivot → entitlement grant retriable-forever), every transition through the transactional outbox, consumers idempotent via natural keys (upsert on userId+contentId). Cache invalidations fan out over RabbitMQ (commands/queues); watch events and QoE telemetry stream over Kafka (facts/log), partitioned by userId with state-carrying, version-guarded events. DLQs are alerting workflows with redrive; trace context rides every message header.
M17M18M15M16M05M24
Heartbeats renew the stream slot (lease) and playback position (absolute values — idempotent by construction) over the existing connection; license renewal mid-stream with a grace window; live key rotation at program boundaries with early manifest signaling and jittered prefetch. Fleet pre-scaled to the event floor hours before (reactive HPA can't beat a vertical edge — M25's control-loop argument); scale-down after the final whistle is slow and staged. Retries everywhere follow one law: one retrying layer, full jitter, budgeted, idempotent-only.
M12M16M23M25M19
SLIs at the user: playback-start success/latency, rebuffer ratio, license success — burn-rate alerts, error budget pre-agreed with product and spent deliberately. Traces tail-sampled (all errors kept), context through every broker hop; async freshness SLO on "purchase → playable"; metrics cardinality governed (device class yes, user ID never — exemplars bridge to traces). Security posture: mTLS workload identity, default-deny east-west from the observed call graph, two-identity discipline (workload cert ≠ user token) — a compromised thumbnail service reaches the image store and nothing else.
M24M21M22
STEP 02

Failure drills — conduct these cold

MANDATORY

For each, narrate: detection signal → blast radius → automatic defenses that engage → the human decision left over. Model answers in the folds, but speak first.

Drill 1 · The entitlement cache cluster dies at minute 12 of the match.
Detection: entitlement-service latency/error burn-rate + cache-hit ratio collapse (M24). License requests fall through to the DB — which the defense-in-depth sized for a bounded multiple, with single-flight collapsing per key (M01) and admission control shedding background traffic first (M14). Breakers on the DB edge convert saturation into fast failures feeding the fallback ladder: serve-stale entitlements from L1/logical-TTL where present, then the pre-signed bounded fail-open for already-playing sessions (M13). In-flight viewers keep watching (licenses already held; renewals hit the grace window — M23). Human decision: extend fail-open scope/duration vs start refusing new joins — the policy doc names who decides. Recovery: warm the rebuilt cluster before readmitting it (M01 warming; M08 slow start), or the recovery causes the second stampede.
Drill 2 · The DRM vendor's license endpoint p99 goes from 80 ms to 6 s. No errors.
The gray failure: error-rate breakers sleep through it — but slow-call-rate thresholds trip (M13's most important config line), and bulkheads cap the threads the vendor edge may hold, so the license service's own pool survives (the M13 pool sim, live). Deadline propagation means requests arriving with <150 ms budget skip the vendor call into the fallback immediately (M07). Retry budget prevents amplification onto the struggling vendor (M12). Blast radius: new premium-tier license issuance degrades; everything else — playback in progress, non-premium, manifests — never notices, because the bulkhead made the failure unable to spread. Human decision: engage the vendor's secondary region/endpoint per runbook, and the comms line to the vendor with your trace evidence (M24).
Drill 3 · A TV app release retries license calls in a tight loop on one error code.
Detection: per-app-version request-rate anomaly (the authenticated version header earning its keep) + license-service admission metrics. Defense already standing: per-device+app-version rate limits at the gateway (M14) cap each broken client; 429+Retry-After feeds any client-side backoff that exists; priority shedding protects playback-critical traffic from the flood; the license service's own admission control guards goodput. Blast radius: the broken version's users degrade (they were degraded anyway — their app is broken); everyone else unaffected. Human decisions: force-update/kill-switch that app version via config, and the retro item — the client SDK's retry policy now goes through the same review as server retry configs (M12's one-law).
Drill 4 · Region failover mid-match: the primary region's load balancers black-hole.
Detection: edge SLIs (user-measured) collapse for the region while pod metrics look green — the measure-at-the-edge argument (M24) cashing out. Traffic moves below DNS where possible (anycast withdrawal / steering policy), DNS records already at moderate TTL with the disobedient tail expected in the RTO math (M11). Stateless playback tier is active/active — surviving region pre-scaled per the event playbook to absorb (M25's N−1 at region scale). The hard parts: session/entitlement caches in region B are cold for the arriving millions — warming + collapsing + shedding is the difference between failover and cascade (M01/M14); the data core promotes per its written RPO with split-brain guarded by external quorum (M11/M03). Human decision: the fail-back timing — after the match, never during, with the reconciliation step the runbook must contain.
Drill 5 · Post-mortem math: the 428 spike you actually had.
Reconstruct with the course's vocabulary: grants written but invalidation events lost or delayed = a dual-write on the invalidation path (M18 — the outbox wasn't under it) or replica-lag read-your-writes anomaly on fresh purchases (M04); players retried a non-transient error code without backoff, amplifying (M12); the error taxonomy collapsed "pending" into "denied" so the player couldn't wait politely (M23/M17 — saga still in its retriable tail). The fixes write themselves as module numbers — which is the point of the course: incidents become compositions of known parts, and RCAs become lookups instead of investigations.
STEP 03

The review: produce the artifacts

MANDATORY
1
The whiteboard run (60–90 min, ideally with an audience). Draw S1→S8 from memory: components, protocols per edge, numbers at 5M concurrent (M02 arithmetic live), and the defense standing at each hop. The pass bar: every box you draw, you can answer "what breaks here and what catches it" without notes.
2
The gap audit against production. Walk your real platform against S1–S8 + the five drills: green (exists and drilled) / yellow (exists, untested) / red (absent). The red list, ranked by the drills it would fail, is a genuine 12-month reliability roadmap — and the document version of this course's value.
3
The one-pager for your leadership. Three investments from the gap audit, each argued in the course's dual currency: user-facing risk (which drill fails today) and money (M25 unit economics). One page. If the course worked, this is easy to write and hard to refuse.
STEP 04

Where next

SKIM
The course's actual thesis, and the reading that extends itYou now hold ~15 primitives — caching, partitioning, consensus-lite, backpressure, idempotency, fencing, budgets — and one discipline: every decision is a trade named out loud, with the failure mode designed rather than discovered. Everything from here is composition. Deepen with: Kleppmann's Designing Data-Intensive Applications (the theory under M03–M05, M15–M19), Google's SRE books (M24–M25 institutionalized), Nygard's Release It! (Week 3 as scar tissue), and the engineering blogs of Netflix/Cloudflare/Discord-class teams for the current state of practice. Then the real curriculum: your own estate's next incident, read as a composition of module numbers — and the design review where you catch it first.

The last habit, and the one that makes the others compound: write the RCA before the incident. Every design doc's "failure modes" section is a pre-written post-mortem — and every drill in §02 you can conduct cold is an incident that will end in minutes instead of hours. That's the difference this month of work bought. Roadmap complete: 26 of 26.