Articles
WebRTC Interview Questions: ICE Candidates, TURN Fallback, and Connection Failures
Practice WebRTC interview diagnosis with offer-answer signaling, ICE candidate delivery, TURN relay fallback, and selected-pair evidence.
“Both users joined the room and exchanged an offer and answer, but neither can see the other.” That WebRTC interview prompt is not solved by saying “check the network.” A strong answer separates signaling from connectivity: did each peer exchange session descriptions, gather and deliver ICE candidates, find a working candidate pair, and establish the media path? TURN is a relay option when direct paths fail, but a successful relay allocation is not proof that audio or video packets flow correctly.
This article uses an original two-peer failure trace and a controlled diagnostic matrix. Evidence boundary: WebRTC.org, the W3C WebRTC specification, and IETF ICE/TURN RFCs support protocol/API behavior. The room incident, logs, and interview response are editorial examples; no candidate report is used for process claims.
First draw four distinct paths
A WebRTC call involves at least four conceptual paths. A signaling channel carries offer, answer, and candidate messages between applications; WebRTC does not prescribe a particular signaling transport. ICE gathers possible network addresses and tests candidate pairs. STUN can help a peer discover its server-reflexive address. TURN allocates a relay address when peers cannot connect directly. Once a pair is selected, media or data uses the negotiated connection. Confusing these stages leads to vague fixes, such as restarting the signaling server when candidate checks are actually failing.
WebRTC.org's peer-connection guide explicitly says that after both peers set local and remote descriptions, the connection is not necessarily ready. Candidates still need to be gathered and transferred. RFC 8445 defines ICE checks on candidate pairs and nomination of a valid pair. In an interview, draw two peers, the signaling server, STUN/TURN services, and direct/relay candidate paths. Then mark which step the observed logs actually prove.
The original exercise has peer A on home Wi-Fi and peer B behind a restrictive corporate network. A and B receive offers and answers. A gathers host, server-reflexive, and relay candidates. B gathers host and relay candidates. The signaling server logs that it forwarded A's candidates, but B's client drops them because a handler closes over the wrong room ID. Direct checks never find a valid pair; B's TURN allocation also later expires after a credential refresh bug. There are two faults, and their timing matters. This is a synthetic case, not a production incident.
Trace the connection before proposing TURN
| Checkpoint | Expected evidence | Fault in the exercise |
|---|---|---|
| Offer/answer | Both peers set local and remote descriptions | Succeeds. |
| Local gathering | icecandidate events produce candidates | Both peers gather some candidates. |
| Signaling delivery | Each remote peer calls addIceCandidate | B drops A's candidates. |
| ICE checks | Candidate pairs receive successful checks | No viable pair can be nominated. |
| Relay allocation | TURN allocation exists with valid lifetime | B's later allocation refresh fails. |
| Media | Selected pair carries packets and tracks render | Never reached in initial failure. |
This table prevents a common reasoning error. The signaling server's “sent” log proves only that it emitted a message. It does not prove B received, parsed, or applied the candidate. Likewise, a local icecandidate event says A gathered a candidate; it does not prove B knows about it. Add a correlation ID for room/session and peer, and log candidate type and delivery status without dumping private addresses or credentials. The useful test is an end-to-end assertion that addIceCandidate is called on the intended remote RTCPeerConnection.
WebRTC.org describes trickle ICE: candidates can be sent as they are found, reducing setup delay compared with waiting for all gathering to finish. That creates ordering concerns in application code. A remote candidate may arrive before the remote description is set; queue it and add it when the peer connection is ready under the chosen signaling design. The API can reject invalid candidates; catch and surface that error with context. Silently dropping candidates makes a signaling-success dashboard misleading.
What candidate types tell you—and what they do not
A host candidate represents an address associated with the peer's network interface. A server-reflexive candidate is learned through STUN and reflects NAT mapping. A relay candidate uses a TURN server allocation. ICE builds local/remote candidate pairs and checks reachability; RFC 8445 discusses pair priority, validation, and nomination. A candidate list is a set of possibilities, not a list of working paths.
For the exercise, A having a relay candidate does not guarantee that B can use it. B must receive the candidate, the candidate pair must be checked, the TURN allocation must be valid, and firewall/protocol policy must permit the path. A corporate network might block UDP, requiring an appropriately configured TURN transport; do not assert a particular fallback transport without inspecting the configuration and network. If a relay pair is selected but media remains blank, move the investigation from ICE selection to track, codec, permission, and packet-flow evidence.
TURN is not merely a public STUN server with a different name. RFC 8656 describes relay allocations with an address, authentication, expiry, permissions, and channel bindings. That state costs bandwidth and needs operational care. A short-lived TURN credential scheme should refresh credentials and allocations correctly, but a credential refresh failure can break long calls or restarts. The server can also be healthy while the client uses the wrong URL, transport, username, or realm.
Don't diagnose a corporate-network failure by making every user relay forever. A relay-first policy may be useful for a specific product or environment, but it increases server cost and can add latency. Measure the share of direct versus relayed selected pairs, connection-success rate by network type, setup time, and relay traffic. The correct answer is conditional: make TURN available and tested; let ICE determine a viable pair under the product's policy; investigate why direct checks failed.
Use state and stats rather than one “connected” boolean
The browser exposes ICE gathering, ICE connection, and overall peer-connection states. WebRTC.org shows listeners for icegatheringstatechange and connectionstatechange. The W3C specification defines the API state machines and statistics surface. Record a time sequence for each peer: description set, gathering started/completed, candidates sent/received/applied, ICE state changes, selected candidate pair, bytes/packets sent and received, and media track events. A single final failed state discards the stage at which progress stopped.
For the synthetic incident, B's logs should show a normal remote description, zero successfully applied remote candidates, then ICE failure. That points to signaling delivery or candidate parsing before it points to codec mismatch. After fixing the room-ID handler, a direct candidate may still fail in the corporate network, but a relay pair can become selected. If the call later drops when B's TURN allocation refresh fails, the time-to-failure and relay stats distinguish it from the initial no-candidate defect.
Be careful with sensitive diagnostics. ICE candidates can expose network addresses; logs should redact or aggregate them as necessary. TURN credentials are secrets and should never be written into client error telemetry. Candidate type, protocol, selected-pair ID, state transition, and error category often suffice for triage. Do not include actual customer IPs in an interview exercise or public post.
A controlled failure matrix
Test three network profiles: peers on the same local network, peers behind ordinary consumer NATs, and one peer behind a restrictive network where direct UDP is unavailable. For each, test with working TURN, deliberately unavailable TURN, and a signaling path that drops candidates. Capture both peers' state transitions and selected-pair type. The controlled conditions make the cause falsifiable.
| Condition | Expected discriminating observation | Likely layer |
|---|---|---|
| Candidate message dropped | Remote peer never calls addIceCandidate | Signaling application. |
| Direct pair blocked; relay available | Relay candidate pair selected and bytes flow | ICE/TURN fallback works. |
| TURN credentials wrong | Relay allocation or checks fail | TURN configuration/authentication. |
| Selected pair connected; no video | Bytes, tracks, codec or rendering need inspection | Media/application path. |
| Call dies after a fixed interval | Allocation/credential expiry or network change suspected | Time-dependent transport state. |
These rows are hypotheses, not automatic diagnoses. A missing addIceCandidate call could be intentional if candidates were embedded in a complete SDP rather than trickled. A “connected” state without video might also indicate an application never attached a remote track to a DOM element. Read the actual implementation and logs before assigning blame.
For a browser demonstration, use a small test harness with two peer connections and a mock signaling channel. Assert that candidate messages carry the correct peer and room IDs, queue until the remote description is ready, and are applied exactly once. Simulate a dropped message and confirm the diagnostic says “candidate delivery missing,” not generic “call failed.” A real network test is still needed to validate TURN connectivity and firewall behavior; a unit test cannot emulate a corporate NAT.
How to communicate the incident answer
Start by saying what the current evidence proves: offer/answer exchange works, so signaling is partly operational, but media connectivity is unproven. Ask for both peers' candidate gathering and application logs, ICE state transitions, and selected-pair stats. If B has no applied remote candidates, fix the room-ID routing and retest. If candidate exchange succeeds but direct checks fail, confirm TURN configuration and credentials and see whether a relay pair is nominated. If it is, inspect packet counters, tracks, and rendering before changing ICE servers again.
State the user impact and recovery behavior. A call setup timeout should surface a clear retry path; a mid-call loss may require ICE restart or a new negotiation according to the application design. Avoid an infinite reconnection loop that repeatedly allocates relay resources or creates duplicate peer connections. Close old connections and media tracks when the room ends. The exact recovery policy depends on latency tolerance and UX, but it should be observable and bounded.
Fast interview answers to common follow-ups
Does offer/answer success mean peers connected? No. It establishes negotiated descriptions; candidates must be exchanged and ICE checks must find a viable pair.
What is STUN for? It helps discover a public-facing NAT mapping. It does not relay media and cannot make every restrictive network traversable.
What is TURN for? It relays traffic when a direct path is unavailable. It requires allocation, authentication, expiry management, and server capacity.
What does an ICE candidate prove? It is a possible route. A successful checked and nominated pair is stronger evidence; packet counters and tracks establish media behavior.
How do you diagnose blank video after connected? Look at selected pair stats, bytes/packets, track events, codec negotiation, browser permissions, and attachment to the UI. Avoid restarting signaling without evidence.
Why trickle candidates? It can reduce setup delay by sending candidates as gathered, but application code must handle message ordering and errors.