Control plane vs data plane: the first split in a video platform
Start from the naive app, let it break, and find the one architectural decision that everything else depends on.
These are first-principles notes on how a large video platform fits together, written the way I work through a design: start with the simplest version and keep asking what breaks first. They describe a generic architecture, not any real company's system.
Requirements
- Authenticated users browse a catalog, search, and play on-demand and live video.
- Subscriptions and device rules decide who may watch what.
- Playback stays smooth for a very large number of concurrent viewers.
Version 0: one server, one database
For a toy project this is fine: login works, metadata works, playback works.
Where it breaks
Put 100,000 users on it. Every viewer now pulls video bytes through the application server. The component meant to answer "is this user allowed to watch this?" has become, by accident, a video delivery network. It was never designed for that job, and it becomes slow, expensive and fragile.
The mistake is mixing two jobs with different scaling characteristics:
- Deciding who can watch what: small, fast, logic-heavy.
- Moving gigabytes to millions of screens: huge, simple, bandwidth-heavy.
The split
| Control plane | Data plane | |
|---|---|---|
| Does | Login, profile, catalog, search, subscriptions, watch history, recommendations, playback authorization | Movies, episodes, live streams, video segments, audio, subtitles |
| Scales with | Roughly linear in user count; cheap per request | Bytes delivered; this is where nearly all the cost lives |
| Built from | Load balancer, stateless API servers, Redis, database | Transcode workers, object storage, CDN |
| Scaling tool | More stateless servers and caches | Edge caching and origin protection |
Playback flow
- The client authenticates, browses the catalog and picks a title.
- It requests playback authorization: subscription, device and region rules are checked.
- The API returns playback information, including where the manifest lives.
- The player fetches the manifest, then requests segments from the CDN, one after another.
To stop unpaid downloads, the data plane relies on entitlement checks, signed URLs, short-lived tokens and DRM. The control plane issues the permission; the data plane enforces it.
Design rules that follow
- Separate control traffic from media traffic. The API never sees a video byte.
- Keep servers stateless. State lives in caches, databases and object storage, so servers can be added freely.
- Move slow work off the request path. Transcoding is a background job, not part of an upload request.
- Protect the origin with a CDN. The origin should see cache misses only.
- Do not split into microservices too early. Separate responsibilities in code first; split deployment when the scaling profiles actually diverge.
Why the split matters more than it looks
It is tempting to read this as "just use a CDN". The deeper point is that the two planes have different growth curves and failure behaviour. Once they are separated, the rest of the design places itself: transcoding, segmentation and cache invalidation live in the data plane; authorization, catalog and recommendations live in the control plane. Most hard problems in streaming reduce to scaling one plane without disturbing the simplicity of the other.
Limits of these notes. They are conceptual: there is no running code, no benchmark and no capacity measurement behind them, so any sizing figure is an exercise rather than a result.