Design a Live Streaming Platform like Twitch

HardMedia & StreamingLive VideoRTMPLow-Latency HLSCDNChat

Problem

Design a live streaming platform like Twitch. Broadcasters stream live video from software such as OBS, and viewers watch with only a few seconds of delay so they can interact with the streamer in real time. Each channel has a live chat room that can be very busy, and broadcasts are recorded so viewers can watch them later. At peak the platform carries 100,000 concurrent live channels and 5 million concurrent viewers, and the most popular channel can draw 1 million viewers at once.

  • What glass-to-glass latency is the target: under 5 seconds, or is sub-second required?
  • Do all channels get multiple quality levels, or only popular or partner channels?
  • What is the maximum broadcaster upload bitrate and resolution, for example 1080p60 at 6 Mbps?
  • How long are past broadcasts kept, and can broadcasters clip highlights?
  • Does chat need moderation tools such as slow mode, bans, and subscriber-only mode?
  • Do we need to support co-streaming or watch parties?

Items in bold are existing requirements. The rest are suggestions. Confirm with the interviewer whether they are relevant first.

  • Ingest a live stream from a broadcaster's encoder.
  • Deliver the stream to viewers with low latency at multiple quality levels.
  • Provide a real-time chat room per channel.
  • Record broadcasts and make them available as on-demand video.
  • Show the live viewer count and whether a channel is online.
  • Let moderators ban users, delete messages, and enable slow mode.

Items in bold are existing requirements. The rest are suggestions. Confirm with the interviewer whether they are relevant first.

  • Glass-to-glass latency of 2 to 5 seconds for most viewers.
  • 5 million concurrent viewers at an average of 4 Mbps is about 20 Tbps of egress at peak.
  • Ingest: 100,000 channels at 6 Mbps is 600 Gbps of inbound video into our points of presence.
  • Transcoding: one 1080p60 input into four renditions needs roughly a few CPU cores or a slice of a hardware encoder per channel, so hundreds of thousands of cores (or a much smaller fleet of hardware encoders) at peak.
  • A busy channel's chat can see thousands of messages per second fanned out to 1 million viewers.
  • A broadcaster's dropped connection should resume the same stream within seconds without viewers losing their place.

Broadcasters push RTMP (or SRT) to the nearest ingest point of presence, which authenticates the stream key and forwards the stream over the backbone to a transcoding cluster. The transcoder produces a ladder of renditions and packages them as low-latency HLS with short partial segments, which an origin serves to a multi-tier CDN that fans out to viewers. Chat runs on a separate WebSocket system with per-channel pub/sub, and the packaged segments are also written to object storage so the broadcast becomes a replay when it ends.

Loading diagram...

Go live. The broadcaster's encoder connects to rtmp://ingest.example/live/{streamKey}, resolved by DNS to the nearest ingest edge. The edge validates the stream key, asks the stream directory to allocate a transcoder in a nearby data center, records the channel as live, and forwards the raw stream to it over the private backbone.

Transcode and package. The transcoder decodes the input and encodes renditions such as 1080p60 source, 720p, 480p, and 160p, aligning keyframes every 2 seconds across all of them. The packager cuts each rendition into 2 second segments made of 0.5 second partial segments, updates the playlists, and makes each partial segment available at the origin as soon as it is encoded.

Watch. The player calls GET /channels/:name/play, which returns a signed master playlist URL on the CDN. The player requests the playlist and uses blocking playlist reloads to learn about each new partial segment the moment it exists, then fetches it from the edge. Edges request each new segment from the mid-tier once and serve it to every viewer waiting for it.

Chat. The viewer opens a WebSocket to a chat gateway and joins the channel. A sent message goes to the chat service, which checks bans, slow mode, and filters, then publishes it on the channel's pub/sub topic. Every gateway with viewers in that channel receives it once and pushes it to its local sockets.

Replay. While live, the origin also writes segments to object storage. When the stream ends, a job assembles a VOD playlist from those segments, so the replay is available almost immediately without re-encoding.

Receives broadcaster streams close to the broadcaster and moves them onto the private network.

  • RTMP and SRT servers in dozens of points of presence, selected by GeoDNS or anycast.

Scalability

Each ingest server handles hundreds of streams, since it only relays bytes. Moving the stream onto the backbone close to the broadcaster avoids the packet loss of long public internet paths, which would otherwise cause stalls for every viewer.

Tradeoffs

RTMP is old, TCP based, and suffers from head-of-line blocking, but nearly every broadcaster tool supports it. SRT (UDP with retransmission) handles lossy uplinks better, so it is offered alongside RTMP. WebRTC ingest is an option for browser broadcasting but is not required by mainstream tools.

Turns one input stream into an adaptive bitrate ladder in real time.

  • FFmpeg-based software encoders for small channels and hardware encoders (GPU or dedicated video ASICs) for the bulk of renditions.

Diagram

Loading diagram...

Scalability

Most of the 100,000 channels have only a handful of viewers, so they get pass-through of the source quality only, plus perhaps one low rendition. The full ladder is reserved for channels above a viewer threshold or partner channels. This cuts transcoding capacity by a large factor without hurting the viewing experience where it matters.

Tradeoffs

Transcoding everything gives every viewer adaptive quality but would multiply the encoding fleet for channels nobody watches. Passing through the source is free but excludes viewers on slow connections, which is acceptable for very small channels.

Serves playlists and segments, and absorbs the fan-out to millions of viewers.

  • Low-Latency HLS (partial segments and blocking playlist reload) over HTTP/2, with a multi-tier CDN.

API

  • GET /channels/:name/play returns { playlistUrl, token }.
  • GET /hls/:channelId/:rendition/playlist.m3u8?_HLS_msn=&_HLS_part= blocks until that part exists.
  • GET /hls/:channelId/:rendition/:segment.:part.m4s returns a partial segment.

Scalability

A channel with 1 million viewers produces only a handful of new parts per second per rendition. Request collapsing at each tier means the origin sees one request per part per mid-tier node, the mid-tier sees one per edge, and only the edges serve each viewer. Live segments are never in the edge cache in advance, so collapsing concurrent misses is what keeps the origin alive.

Tradeoffs

Standard HLS with 6 second segments gives 15 to 30 seconds of delay, too slow for streamer interaction. WebRTC gives sub-second delay but requires stateful media servers for every viewer and loses CDN caching. Low-latency HLS reaches 2 to 5 seconds while staying on cacheable HTTP, the right balance for broadcast-scale audiences.

Real-time chat rooms per channel, with moderation.

  • WebSocket gateways in Go or Elixir, and a pub/sub layer (such as NATS or Redis Pub/Sub) sharded by channel.

Data Model

  • chat_messages: channel_id (partition key), sent_at (clustering key), message_id, user_id, text, is_deleted, stored for moderation history.
  • channel_bans: channel_id, user_id, expires_at.

Scalability

Gateways subscribe to a channel's topic only while they have viewers in it, so a message to a 1 million viewer channel spread over 500 gateways is 500 internal deliveries. At thousands of messages per second, gateways batch messages into frames every 100 to 200 ms. Huge channels use slow mode or follower-only mode, which also keeps chat readable.

Tradeoffs

Chat is separate from video so a chat outage never interrupts the stream and each scales on its own. Messages are delivered at most once; a reconnecting client does not replay missed chat, which keeps the system simple and matches user expectations for a fast-moving room.

Tracks which channels are live, where their transcoder runs, and current viewer counts.

  • A strongly consistent key-value store (etcd or a replicated database) for live channel state, and a cache for directory pages.

Data Model

  • live_streams(channel_id, stream_id, ingest_pop, transcoder_id, started_at, status)
  • viewer_counts(channel_id, count, updated_at), updated from CDN and player heartbeats every 30 seconds.

Tradeoffs

Viewer counts are approximate and refreshed periodically from aggregated heartbeats, because counting connections exactly across thousands of CDN edges in real time is costly and adds no value to viewers.

Related questions