Skip to content

Build1 publisher3 min readPublished

Two of WebRTC's three ICE candidate types depend on servers you operate

The spec's three JavaScript APIs handle codecs, encoding and transport once two peers have found each other. Finding them takes a signaling service, STUN and TURN, and all three are yours to run and budget for.

The Engineer · Build desk

Illustration accompanying Two of WebRTC's three ICE candidate types depend on servers you operate

What happened

  • WebRTC handles the media path once two peers have found each other, covering codec negotiation, encoding and transport, and the standard stops short of the finding part.
  • Peers must first exchange SDP capability descriptions, and the spec ships no mechanism to deliver them, leaving signaling to the implementer, typically over WebSockets or HTTP long polling.
  • Regular ICE sends nothing until every candidate is gathered, so negotiation cannot begin until the slowest candidate completes.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • cost The relay bill is metered by call duration, not by connection attempts, so whoever runs TURN pays for the full length of every call that cannot go direct.
  • constraint Call setup is only as reliable as a service you wrote, and universal browser support for the APIs tells you nothing about that service's uptime.
  • decision Before anyone argues about mesh against SFU, the team has already committed to operating three services the spec does not provide.
  • capability RTCDataChannel puts chat, file chunks or game state on the same connection as the media, so an application does not need a second transport for data that needs no codec.

Count the description calls in the handshake that dev.to's "WebRTC at Scale" prints. Peer A creates an offer and calls setLocalDescription. Peer B runs that offer through setRemoteDescription, creates an answer, calls setLocalDescription on it. A closes the loop with setRemoteDescription [10]. Four calls, two on each side [12]. The guide is blunt about the rest: "setLocalDescription and setRemoteDescription are the only two calls doing any real work here. Everything else is just getting the SDP blob from one peer's signaling connection to the other's" [11].

That "everything else" is the two sends in the snippet, and it is your code. Which protocol carries it is the implementer's pick, and the guide says builders typically use WebSockets or HTTP long polling [8]. So the first service a WebRTC product needs is one whose entire job is moving two blobs of text between two browsers on every call attempt [25].

The second thing you supply is reachability. SDP tells each peer what the other supports, not where it is, and most devices sit behind NAT or a firewall with no directly routable address [13]. ICE fixes that by gathering every address a peer might answer on and testing pairs until one connects [14]. A peer gathers three kinds at once: a host candidate from its own interface, a server-reflexive candidate from STUN carrying the public IP and port the NAT mapped it to, and a relay candidate allocated on TURN [15]. One of the three is free. The other two come from servers someone operates, and for TURN that someone is you [16].

STUN is a question and an answer: the peer asks what address its NAT mapped, then uses it as a candidate [17]. TURN is the expensive path. Symmetric NAT and some firewall configurations block direct connectivity outright, so TURN relays traffic between the peers instead [18]. It works in every configuration STUN cannot, and the price is that every packet crosses a third server, adding latency and consuming that server's bandwidth for the duration of the call [19].

Setup latency divides on the same servers. Regular ICE holds every candidate until gathering completes, which is simple and means negotiation cannot start until the slowest candidate is in [20]. Trickling ICE sends each candidate the moment it is found [21]. A slow TURN allocation under regular ICE therefore delays the start of negotiation on every call, including the ones that would have connected host-to-host [26].

The guide frames the mesh/SFU/MCU choice as the tradeoff that decides how the media itself scales, and its contents list sections on an example implementation and on scaling the topology [22][23]. The published text breaks off mid-sentence in the trickling ICE paragraph, before those sections [24]. On what is there, the topology claim is asserted rather than worked through, while signaling and traversal are shown in code.

I think the omission in the standard is the right call. Rooms, identity and auth live in the signaling path, and a spec that had picked WebSockets would have been wrong for anyone using long polling. It does mean the availability of your calls is the availability of a service you wrote, and every browser shipping the APIs leaves that number to you [27].

What to watch

  • The rest of the guide's "Scaling the Topology" section, which would show whether mesh, SFU and MCU are compared with measurements or only described.
  • The example signaling implementation's handling of reconnects and room membership, neither of which appears in the offer/answer snippet.
  • Measured setup times for trickling against regular ICE on your own mix of networks, since the gain depends on how often TURN is the slow candidate.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories