← System design

Media & Streaming

Design Live Streaming Platform

A live stream is a video file that does not exist yet. Frames leave a creator's webcam, cross the internet to you, get re-encoded into several qualities, cut into small pieces and copied to edge servers worldwide, and a viewer on a phone in another country should see them about three seconds later. Next to the video runs a chat room that may hold half a million people typing at once. Both have to keep up with an audience that can multiply in a minute when a famous streamer goes live.
Core: transcode ladder + CDN segment fan-out9M concurrent viewers at peakGlass-to-glass under 4 sChat fan-out per channel

01

The problem

01

The problem

Build a platform where anyone can broadcast live video and anyone else can watch it, in the style of Twitch, Kick or YouTube Live. Creators send one high quality stream from software like OBS. Viewers pick a channel and get smooth playback at whatever quality their network allows, plus a live chat. When a broadcast ends, it is kept as a replay for a while.

What makes this hard is the combination of three pressures. Video is expensive to process: every incoming stream needs real-time encoding into four or five renditions. Delivery is enormously asymmetric: one input becomes millions of outputs, and the popularity of channels is extremely skewed. And everything is on a clock, because a stream that falls ten seconds behind feels broken when chat is reacting to something the viewer has not seen yet.

Scope it out loud

Say what you are leaving for later: payments and subscriptions, ads, clips, moderation tooling and recommendations. Keep ingest, transcoding, delivery, chat and replay in scope. That is already a full hour.

02

What the platform must do

02

What the platform must do

Functional
  • A creator authenticates with a stream key and pushes video over RTMP or SRT.
  • Viewers watch any live channel with adaptive quality from 160p up to the source resolution.
  • Each channel has a chat room where messages appear for everyone within about a second.
  • A directory lists live channels by category and current viewer count.
  • Finished broadcasts are saved and playable as replays for 14 days.
  • Creators see live health stats: incoming bitrate, dropped frames, viewer count.
Non-Functional
  • Glass-to-glass latency, camera to viewer screen, under 4 seconds in low latency mode, under 10 in normal mode.
  • Rebuffering under 0.5 percent of watch time.
  • A single channel can grow from a few hundred to over a million viewers without anyone else's stream suffering.
  • If an ingest server or transcoder fails, the stream recovers in a few seconds without the creator restarting.
  • Chat favours availability over perfect ordering: losing an occasional message is better than freezing the room.
The latency question

Ask what latency the product needs. "Under 4 seconds" works with HTTP segments and a CDN. "Under 500 milliseconds" means WebRTC and a completely different, far more expensive delivery tier. Most streaming platforms choose the first and offer the second only for special cases such as auctions or betting.

03

Sizing the load

03

Sizing the load

Take a peak evening with 90,000 channels live at once and 9 million concurrent viewers. Assume creators send 1080p60 at 6 Mbps and viewers average 3.5 Mbps across the ladder. Chat is busiest in the largest channels.

QuantityWorkingResult
Ingest bandwidth90K x 6 Mbps540 Gbps into our edge
Egress bandwidth9M x 3.5 Mbpsabout 31.5 Tbps, almost all from CDN
Fan-out ratio31.5 Tbps / 540 Gbpsabout 58 out for every bit in
Transcoded channelschannels with 5+ viewers, about 40%36,000 full ladders
Transcode computeone ladder about 8 vCPU on software x264about 290K vCPU, or a few thousand GPU sessions
Segments created36K ladders x 5 renditions / 2 s partsabout 90K objects / s
Origin requests after CDNtwo tier cache, 99.5% hit ratioa few thousand / s per region
Replay storage per day90K x 3 h average x 6 Mbps source onlyabout 730 TB, kept 14 days
Chat messages9M viewers, about 2% typing, 1 message every 20 sabout 9,000 / s in
Chat deliveriesskewed to big roomstens of millions / s out
Two different scaling problems

Ingest and transcoding grow with the number of channels. Delivery and chat grow with the number of viewers, and mostly with the viewers of a few huge channels. You cannot serve 31 Tbps from your own origin, so the design is really about producing segments once and letting a CDN multiply them.

Not every channel needs a ladder

Most live channels have almost no viewers. Pass their source through untouched and only start transcoding once a channel crosses a viewer threshold. That alone cuts transcode spend by more than half.

04

API and protocols

04

API and protocols

POSTrtmps://ingest-fra.example.tv/app/{stream_key}Creator pushes video
// Not REST: OBS opens a long-lived RTMPS or SRT connection // The stream key maps to a channel; it is secret and rotatable video: H.264 1080p60, keyframe every 2 s audio: AAC 48 kHz stereo bitrate: up to 8 Mbps
GET/v1/channels/{login}/playbackStart watching
{ "live": true, "broadcast_id": "bc_7Q2ZK", "manifest": "https://edge.example-cdn.net/live/bc_7Q2ZK/master.m3u8?tok=eyJ...", "low_latency": true, "chat": "wss://chat.example.tv/rooms/ch_88812" } // The signed token expires in 10 minutes; players refresh it in the background
GET/live/{broadcast}/720p/index.m3u8Rendition playlist, served by the CDN
#EXT-X-TARGETDURATION:2 #EXT-X-PART-INF:PART-TARGET=0.5 #EXT-X-MEDIA-SEQUENCE:48211 seg48211.m4s #EXT-X-PART:DURATION=0.5,URI="seg48212.p0.m4s" #EXT-X-PRELOAD-HINT:TYPE=PART,URI="seg48212.p1.m4s"
POSTchat frame over WebSocketSend a chat message
{ "op": "say", "room": "ch_88812", "text": "that clutch was unreal", "nonce": "a91f" } // Server echoes with an id and timestamp, or a "slow_mode" rejection
GET/v1/directory?category=chess&cursor=...Browse live channels
// Sorted by viewer count, refreshed about every 30 s, served from cache
Video does not go through your API

The application API hands out a manifest URL and a chat address, and then gets out of the way. Every video byte flows from ingest to transcoder to origin to CDN to player, on infrastructure built for that, never through the same servers that answer directory requests.

05

Architecture overview

05

Architecture overview

Ingest, processing and deliveryDiagram
flowchart LR
	OBS["Creator encoder"] --> IN["Regional ingest PoP"]
	IN --> AU["Stream key auth"]
	IN --> TR["Transcoder: ladder and packager"]
	TR --> OR[("Origin segment store")]
	TR --> AR[("Replay archive")]
	OR --> SH["Origin shield"]
	SH --> CDN["CDN edges"]
	CDN --> P["Viewer player"]
	P --> API["Playback API"]
	P <--> CH["Chat edge servers"]
	CH <--> PS[["Room pub/sub"]]
	TR --> ST["Stream state service"]
	ST --> DIR["Directory and counts"]

A creator's encoder connects to the nearest ingest point of presence, picked by DNS or anycast. Ingest servers are thin: they check the stream key, accept the RTMP or SRT session and forward the raw stream over the provider's backbone to a transcoding cluster in the same region. Keeping the first hop short matters because packet loss on the creator's last mile is the most common source of stutter.

The transcoder decodes the source and re-encodes it into a ladder, perhaps 1080p60, 720p60, 480p, 360p and 160p, all aligned on the same keyframe boundaries so the player can switch between them cleanly. A packager cuts each rendition into short CMAF segments and partial segments, writes them to an origin store, and updates the playlists. A copy of the source rendition goes to the replay archive.

Viewers never touch the origin directly. Their players fetch playlists and segments from CDN edges, which fall back to a regional origin shield on a miss, which falls back to the origin. Chat is a separate system that shares nothing with the video path except the channel ID.

Ingest PoPs

Dozens of small sites near creators. Stateless apart from the open connection, so a creator who reconnects can land on any server and the broadcast ID stays the same.

Transcode cluster

GPU or dedicated encoder hosts with a scheduler that places each channel on a slot. Popular channels get a hot standby on a second host.

Origin and shield

Segments live in memory and on fast disk for a few minutes, since nobody asks for a live segment from an hour ago. The shield collapses requests so each segment leaves the origin once per region.

Chat

WebSocket edge servers hold viewer connections and subscribe to the rooms their clients are in. A pub/sub tier routes each message to the edges that care.

06

Deep dive: from webcam to a million screens

06

Deep dive: from webcam to a million screens

Where the latency hides

Glass-to-glass delay is the sum of many small waits: encoding at the creator, the network to ingest, transcoding, waiting for a segment to finish, CDN propagation, and the player's buffer. The single biggest number is usually the segment length multiplied by how many segments the player buffers.

From a frame at the creator to a frame on screenDiagram
flowchart LR
	A["Camera frame"] --> B["Encoder, about 100 ms"]
	B --> C["Network to ingest, 50 to 150 ms"]
	C --> D["Decode and re-encode, 300 to 600 ms"]
	D --> E["Packager writes 0.5 s part"]
	E --> F["Origin to edge, 100 to 300 ms"]
	F --> G["Player buffer, 3 parts"]
	G --> H["Frame on screen"]

The transcode ladder

A viewer on hotel Wi-Fi cannot sustain 6 Mbps, so you encode the same picture several times at different sizes and let the player choose. A sensible ladder is the source at 1080p60, then 720p60 at about 3.5 Mbps, 480p at 1.5 Mbps, 360p at 0.8 Mbps and an audio-heavy 160p for poor connections. Every rendition must put keyframes at exactly the same timestamps, typically every two seconds, because the player can only switch rendition at a keyframe.

Transcoding in real time is the main compute bill. Software x264 at a fast preset gives good quality per bit but needs a lot of CPU for 1080p60. Hardware encoders on GPUs or dedicated chips are far cheaper per stream with slightly worse compression. Large platforms often mix both: hardware for the long tail, careful software encodes for the biggest channels where every saved bit multiplies across a million viewers.

To avoid paying for ladders nobody watches, start every new broadcast in passthrough mode where viewers get only the source. When the viewer count crosses a threshold, perhaps five, the scheduler assigns a transcoder slot and the master playlist gains extra renditions on its next refresh.

From a continuous stream to cacheable files

CDNs are excellent at serving files, so we turn video into files. The packager cuts each rendition into fixed-length segments in CMAF (fragmented MP4) and writes a playlist that lists the most recent few. Players poll the playlist, download new segments and play them in order. The playlist is the only object that changes; the segments are immutable and can be cached with long lifetimes.

With classic 6-second segments and a three-segment buffer, latency lands near 20 seconds. Shorter segments help, but a 1-second segment means a keyframe every second, which hurts compression. Low-Latency HLS solves this by publishing partial segments of about half a second as they are produced, while full segments keep their two-second keyframe interval. The playlist advertises the next part before it exists, and the player issues a blocking request that the edge holds open until the part arrives. With three parts buffered, the player sits around 1.5 seconds behind the live edge.

Fanning out through the CDN

When a big channel goes live, hundreds of thousands of players ask for the same new part within the same half second. Without care, each CDN edge misses and asks the origin at once. Two mechanisms stop that. Request collapsing at the edge sends one upstream fetch per object and parks the other requests on it. An origin shield per region adds a second layer, so the origin sees a handful of requests per segment, not one per edge.

Playlists need a short TTL, about half the part duration, while segments can be cached for minutes. For the very largest events you can pre-position by pushing segments to edges instead of waiting to be pulled, or spread the load across two CDN providers with a traffic steering layer that shifts viewers when one degrades.

Chat beside the video

Viewers connect to a WebSocket edge, which subscribes to the room on a pub/sub tier. When someone sends a message, the edge validates it, applies rate limits and moderation filters, and publishes it to the room. Every edge holding members of that room receives one copy and writes it to each local socket. A room of 500,000 people spread over 400 edges costs 400 internal deliveries per message, not 500,000.

Huge rooms produce more text than anyone can read. Past a few hundred messages per second, the edge samples or batches, sending a bundle every 200 milliseconds. Nobody notices a dropped "LUL" among thousands; everybody notices a frozen chat.

Keep chat and video in sync

If video is 4 seconds behind and chat is 300 ms behind, chat spoils what is about to happen. Players know their own latency, so they can delay rendering chat messages to match the video position, using the server timestamp on each message.

07

Decisions and what they cost

07

Decisions and what they cost

Chosen
Low-Latency HLS over a CDN

Two to four seconds of delay, works in every browser and phone, and rides on commodity CDN capacity measured in tens of terabits. The cost is a more complex packager and players that support blocking playlist reloads.

Default delivery
Rejected as default
WebRTC to every viewer

Sub-second delay, ideal for auctions or co-streaming. But each viewer needs a stateful session on a media server, so delivering 9 million streams means building your own global CDN for real-time media.

Only for special features
Chosen
2 s segments with 0.5 s parts

Keyframes every two seconds keep compression efficient, while parts let the player stay close to the live edge. Edges and origin handle about four times more requests than with plain segments.

Balanced
Alternative
6 s segments

Fewer requests, higher cache efficiency and better quality per bit, with 15 to 25 seconds of delay. Fine for broadcast events where nobody is chatting, poor for interactive streams.

Normal latency mode
Chosen
Transcode on demand above a viewer threshold

Most channels never pay for a ladder. The small cost is that the first few viewers of a new stream may only get the source rendition, which can be heavy on mobile.

Big cost saving
Rejected
Full ladder for every broadcast

Simple and uniform, but it more than doubles the transcode fleet to serve channels watched by nobody.

Wasteful
Chosen
Chat via edge servers and room-level pub/sub

One internal message per edge per room keeps internal traffic proportional to the number of servers, not viewers. Ordering is per publisher only, which chat tolerates.

Scales with rooms
Rejected
Persist every message before delivery

Gives a perfect, ordered history, but puts a database write on the hot path of millions of deliveries. Write to a log asynchronously instead, for moderation and replays.

Too slow at peak

08

Failure modes

08

Failure modes

📡
The creator's connection drops for five seconds

Home upload links flicker. If the platform treats every disconnect as the end of a broadcast, viewers get an "offline" screen and the replay splits in two.

Hold the broadcast open for a grace period of about 30 seconds, show a "reconnecting" slate in the playlist, and resume the same broadcast ID when the encoder returns, on any ingest server.
🔥
A transcoder host dies mid-stream

Every channel on that host stops producing segments. Players hit the end of the playlist and start buffering.

The scheduler sees missed heartbeats within two seconds and moves the channel to a spare slot. For channels above a viewer threshold, run a hot standby transcoder that the packager can switch to without a gap.
🌊
A celebrity goes live without warning

A channel goes from zero to 1.5 million viewers in ten minutes. Edges in one country saturate and the origin shield sees a burst of misses for each new part.

Request collapsing and shields keep origin load flat. Steer part of the audience to a second CDN, and let players drop a rung on the ladder automatically when they see slow downloads.
💬
Chat flood in a massive room

A raid or a big play sends 20,000 messages a second into one room. Edges spend their CPU serialising text and sockets start to lag behind.

Switch the room to slow mode automatically, batch deliveries every 200 ms, and sample messages above what a person can read. Rate limits per user keep spam bots in check.
🔑
A stream key leaks

A creator shows their key on screen. Someone else connects and broadcasts on their channel.

Allow one active session per key and alert the owner on a takeover attempt, offer one-click rotation, and keep keys hidden by default in the dashboard.
🧭
Players drift far behind live

After a few stalls, a player is twelve seconds behind and chat makes no sense to that viewer.

Players compare their position with the program date time in the playlist and catch up by playing slightly faster, or jump to the live edge if they fall more than a set distance behind.

09

How to handle the interview

09

How to handle the interview

1

Split the problem into ingest, process, deliver and chat. Each has a different bottleneck, and saying that early gives the interview a clear structure.

2

Compute the fan-out ratio. Showing that egress is fifty times ingest explains why the CDN is the system and the origin should be protected at all costs.

3

Build a latency budget. List each stage with milliseconds attached and show which knob, mostly segment and part length, moves the total.

4

Know why keyframes must align across renditions. It is a short detail that proves you understand adaptive bitrate rather than reciting acronyms.

5

Raise the transcode cost yourself. Point out that most channels have few viewers and propose transcoding on demand. Interviewers like candidates who notice money.

6

Answer the thundering herd question with layers. Edge collapsing, origin shield, multi-CDN. Then mention players stepping down the ladder.

7

Treat chat as a separate design. Show that edge-level fan-out makes room size cheap, and that sampling is acceptable in huge rooms.

8

Explain when you would choose WebRTC. Name the use case (sub-second interaction) and the cost (stateful media servers per viewer), and keep it out of the default path.

10

Growing the design in stages

11

Growing the design in stages

Stage 1: a few streams, a few hundred viewers
One media server

An open source media server accepts RTMP and writes HLS to local disk, served by a web server. Latency is about 15 seconds and there is no transcoding. Enough to prove the product.

Stage 2: thousands of viewers
Put a CDN in front

Segments move to an origin store and a CDN serves viewers. Chat moves to its own WebSocket service with a simple pub/sub.

Stage 3: thousands of channels
Regional ingest and a transcode scheduler

Ingest PoPs open near creators, and a scheduler places channels on GPU transcoder slots with on-demand ladders. Viewers finally get adaptive quality.

Stage 4: millions of viewers
Low latency and origin protection

Partial segments bring delay under four seconds. Origin shields and request collapsing protect the origin, and the single-origin delivery model is retired.

Stage 5: global platform
Multi-CDN and owned edge capacity

Traffic steering spreads viewers across CDNs, and the largest platforms place their own caches inside ISPs to cut transit costs.

Watch and read

Try next

Free to read · better with landed

Whiteboard this with landed

landed runs it as a live system design round on the whiteboard and grades your trade-offs.