Engineering Atlas › System Design Fundamentals

Peer-to-peer media with WebRTC

11 min read · last reviewed 2026-10-17

Open in the interactive app: practice, quiz, mock interview →

In one minute

How it works

Signalling and SDP

Each peer creates an offer or answer in SDP format describing codecs, media tracks, encryption fingerprints and ICE credentials. Your application carries these between peers over any channel. WebRTC is agnostic here, which is why every product has its own signalling server handling rooms, auth and presence. The one place a standard now exists is broadcast ingest: WHIP (RFC 9725, March 2025) sends the SDP offer as an HTTP POST and gets the answer back in the response, so an encoder such as OBS can publish to any compliant media server (RFC 9725).

The stack underneath is all standardised and was refreshed around 2018 to 2020, so older articles cite superseded numbers: ICE is RFC 8445 (replacing 5245), STUN is RFC 8489 (replacing 5389), and TURN is RFC 8656 (replacing 5766). The browser API itself is a W3C Recommendation, last revised in March 2025 (W3C).

ICE, STUN and TURN

Most devices sit behind NAT, so a peer does not know its public address. ICE gathers candidates:

Peers exchange candidates (trickle ICE sends them as they are found), pair them, sort pairs by priority, and run connectivity checks: STUN binding requests sent directly on each pair. The first successful high-priority pair is nominated. Host and reflexive pairs work across most home NATs. Symmetric NATs and strict corporate firewalls defeat hole punching, and then only the relay works, often over TCP or TLS on port 443.

Media transport

Media is encrypted with SRTP using keys negotiated by DTLS over the same path. Audio is typically Opus at 20 to 40 kbps; video VP8, VP9, H.264 or AV1 at 0.3 to 2.5 Mbps. Congestion control estimates available bandwidth from packet delay trends and loss and adjusts the encoder bitrate every few hundred milliseconds. Loss is handled with NACK retransmissions for video, forward error correction for audio, and jitter buffers, all tuned to keep end-to-end delay below roughly 150 to 300 ms. Data channels run SCTP over DTLS and can be reliable or unreliable, ordered or unordered (RFC 8831).

Topologies for groups

In a mesh, each participant sends its stream to every other one: upload grows linearly with participants. An SFU (selective forwarding unit) receives one upload per participant and forwards streams to others without decoding, often choosing among simulcast layers (for example 180p, 360p, 720p) per receiver based on their bandwidth. An MCU decodes and mixes into one stream, which is cheap for clients but very CPU-heavy on the server.

Down the stack

Layer 1The contract

The WebRTC API promises an encrypted connection between two endpoints that both consented to it, with media delivered in real time on a best-effort basis: late data is worth less than missing data, so the stack trades completeness for latency. Data channels let you choose per channel between reliable and unreliable, ordered and unordered delivery. Connection state is reported through events (checking, connected, disconnected, failed), and nothing guarantees a path exists at all; without TURN, some pairs of networks simply cannot connect.

Layer 2The mechanism

Candidates appear in SDP as lines like a=candidate:1 1 udp 2130706431 192.168.1.20 54400 typ host: foundation, component, transport, priority, address, port and type. Connectivity checks are STUN Binding requests carrying USERNAME (the two ICE ufrags joined), MESSAGE-INTEGRITY (HMAC-SHA1 keyed with the ICE password), PRIORITY, and ICE-CONTROLLING or ICE-CONTROLLED with a tie-breaker; the controlling side adds USE-CANDIDATE to nominate. Pairs move through Frozen, Waiting, In-Progress, Succeeded and Failed states (RFC 8445), and consent checks repeat about every 5 seconds (randomised by plus or minus 20%) so a peer that stops answering loses consent, and the sender must stop, after 30 seconds (RFC 7675). DTLS then runs over the nominated pair, each side verifying the certificate fingerprint from the SDP, and exports SRTP keys. Media rides RTP, with a 12-byte header holding sequence number, timestamp and SSRC. RTCP feedback carries NACKs, PLI keyframe requests and transport-wide congestion control reports that drive a delay-based bandwidth estimator. TURN relays use Allocate, CreatePermission and ChannelBind, after which data uses a 4-byte ChannelData header instead of a 36-byte Send indication (RFC 8656).

Layer 3The machine

Packets are kept near 1,200 bytes to avoid IP fragmentation across unknown paths. An Opus frame of 20 ms is 50 to 100 bytes of payload, while RTP, the SRTP auth tag, UDP and IPv4 headers add about 50 bytes, so audio pays roughly 40% header overhead at 50 packets per second. Video at 1.2 Mbps is about 125 full packets per second, and a keyframe can be ten times a delta frame, producing bursts that congestion control must absorb. NATs expire idle UDP bindings in 30 to 120 seconds, which is why STUN keepalives flow every 15 to 25 seconds; ICE says agents should use 15 seconds and must not go lower (RFC 8445). Jitter buffers hold 20 to 200 ms of audio, adapting to measured arrival variance. Encoding runs on hardware encoders where available, because a 720p software encode can take a full CPU core on a phone.

Why it's built this way

  1. Conversation tolerates about 150 ms of one-way delay but not stalls, so media uses UDP, limited retransmission and adaptive bitrate.
  2. IPv4 scarcity put most devices behind NAT, so ICE probes many paths and keeps TURN as a last resort.
  3. Browsers must not become tools for sending traffic to arbitrary hosts, so connectivity checks need credentials and encryption is mandatory.
  4. Network quality varies wildly within one call, so congestion control adjusts every few hundred milliseconds and SFUs pick simulcast layers per receiver.
  5. Upload bandwidth is scarcer than download, so group calls send one stream up to a server rather than one per peer.

Diagram

sequenceDiagram
    participant A as "Peer A"
    participant S as "Signalling server"
    participant T as "STUN/TURN"
    participant B as "Peer B"
    A->>T: STUN binding request
    T-->>A: your public addr 203.0.113.5:40100
    A->>S: offer SDP + candidates
    S->>B: offer
    B->>T: allocate relay
    B->>S: answer SDP + candidates
    S->>A: answer
    A->>B: ICE connectivity checks on candidate pairs
    B-->>A: check succeeds, pair nominated
    A->>B: DTLS handshake, then SRTP media

Worked example

A telehealth product runs 5,000 concurrent one-to-one video calls at 1.2 Mbps per direction, and plans group sessions of 8.

TURN sizing: if 15% of calls fall back to relay, that is 750 calls. A relayed call carries both directions in and out of the TURN server: 750 x 2 x 1.2 Mbps = 1.8 Gbps in and 1.8 Gbps out. At a typical cloud egress price of around $0.05 to $0.08 per GB, 1.8 Gbps for an 8-hour business day is about 6.5 TB per day, or roughly $330 to $520 daily, so TURN servers are placed in regions near users and on providers with cheaper bandwidth.

Group sessions: in a mesh of 8, each participant uploads 7 streams at 1.2 Mbps, 8.4 Mbps, which most home uplinks and phone batteries cannot sustain. With an SFU and simulcast, each participant uploads about 1.2 + 0.5 + 0.15 = 1.85 Mbps once, and downloads 7 streams chosen by layout, perhaps one 720p speaker at 1.2 Mbps and six 180p tiles at 0.15 Mbps, about 2.1 Mbps. At about 17 Mbps out per room, one 10 Gbps SFU node handles a few hundred rooms.

In the wild

Trade-offs

OptionStrengthsWeaknessesChoose when
Peer-to-peer meshNo media servers, lowest latencyUplink grows with N, poor beyond 3 to 4One-to-one calls
SFUScales to dozens, simulcast per receiverServer bandwidth, more downlink per clientGroup video, webinars with interaction
MCUOne stream per client, easy recordingHeavy server CPU, added latencyLow-power clients, legacy endpoints
TURN alwaysPredictable connectivity, hides IPsBandwidth cost and added hopStrict privacy or enterprise networks

Pitfalls in production

Leadership lens

Check yourself

  1. Why can two peers both behind home NATs often connect without TURN?

    Show answer

    Each learns its public mapping via STUN, and simultaneous connectivity checks open NAT bindings in both directions, so packets get through.

  2. Why does an SFU scale better than a mesh for the sender?

    Show answer

    The sender uploads one set of streams to the SFU instead of one copy per participant, so upload stays constant as the room grows.

  3. What is signalling and why does WebRTC leave it to you?

    Show answer

    It is the exchange of SDP offers, answers and candidates. Apps already have their own identity, rooms and transport, so the standard avoids prescribing one.

Sources and further study

Primary

Systems docs

Books

Other curricula

Watch

Free resources

Open in the interactive app: practice, quiz, mock interview →