There is exactly one latency number a caller feels: how long the line stays silent after they stop talking before the agent starts talking back. Everything on this page exists to explain that number, break it into hops you can attack one at a time, and show you how to measure yours instead of trusting ours. We call it turn latency: the wall-clock gap from end-of-user-speech to first audio-out. It is the sum of five hops — capture, encode, transport, runtime, egress — plus one thing people forget to count: the endpointing window your turn detector waits before it even decides the user is done.

The five hops

A turn walks the same path in both directions. The user’s audio climbs capture → encode → transport → runtime; the reply comes back runtime → transport → egress. Here is where the time goes and what actually dominates each hop.
HopWhat happensWhat dominates itMeasured how
CaptureMic → frames. Browser runs AEC/AGC/NS + jitter buffer; a phone leg is G.711 off the wireOne frame of buffering (20 ms) + the browser’s own jitter bufferClient-side frame timestamps
EncodeOpus (browser/app legs) or G.711 (phone legs); runtime bus is 8 kHz PCM16Codec frame boundary — Opus is 20 ms/frame, ts_delta = 960 on a 48 kHz clockSDK capture-to-publish delta
TransportEncoded frames ride MoQT over WebTransport/QUIC on a single :443, or RTP for phone legsOne network RTT/2 each way; congestion statePer-connection transport telemetry (RTT, cwnd)
RuntimeASR → LLM → TTS (cascaded) or one speech-to-speech modelAlmost always the LLM’s time-to-first-token, or the S2S model’s prefillRuntime per-node tracing
EgressReply PCM → 20 ms pacer → Opus/G.711 back to the callerThe paced 20 ms tick; one frame of look-aheadEgress pacer timestamps
The runtime hop dominates the total by an order of magnitude. Transport and codec hops are single- to low-double-digit milliseconds; a cascaded ASR→LLM→TTS turn is hundreds. If you are chasing latency, start at the runtime and only then tune transport. This page gives you both, in that order.

Capture and encode

On a browser or app leg the audio pipeline is the browser’s own — reused, not replaced. A loopback RTCPeerConnection runs echo cancellation, gain control, noise suppression, the Opus encoder, and the jitter buffer; an RTCRtpScriptTransform in a Worker taps the encoded Opus frames and hands them to the transport. See WebRTC diversion for the capture path in detail. The floor here is one Opus frame — 20 ms — plus whatever depth the browser’s jitter buffer settles to on your network. On a phone leg there is no browser pipeline: G.711 arrives in 20 ms RTP packets, the media plane decodes to 8 kHz PCM16, and noise suppression runs on ingress before the audio reaches the runtime. There is deliberately no acoustic echo cancellation or AGC in the media path — PSTN legs lean on VAD-gating instead, which is a correctness choice, not a latency one.
Do not confuse the 20 ms tick (160 samples at 8 kHz) with turn latency. The tick is the frame cadence the whole pipeline paces on; it bounds jitter, not the turn. A single tick is ~20 ms; a turn is hundreds because the model has to think.

Transport: QUIC earns its place here

This is the hop where our transport choice shows up as a number. In a controlled prototype rig over a WAN link (50 ms RTT, ~1% loss), measuring the same turn — end-of-user-speech to start-of-agent-speech — over QUIC versus a TCP+TLS baseline:
Turn latency (prototype rig, 50 ms RTT, ~1% loss)QUICTCP + TLS
p5091.2 ms193.0 ms
p9991.9 ms193.8 ms
QUIC roughly halves the turn and, more importantly, keeps the tail flat — p99 sits right on p50 because head-of-line blocking is gone. Under concurrency (c = 20) the gap widens where it hurts most: time-to-first-token p50 93.9 ms vs 143.6 ms (−35%), and p99 149.2 ms vs 1197.9 ms — an ~8× better tail — with ~60% more throughput.
These are prototype numbers from a purpose-built rig, not a measurement of the production stack. Treat them as directional evidence for the transport choice, not a latency SLA. The productionized transport lives on the same :443 QUIC plane; measure your own turn (below) before quoting a figure. Cost and scale figures live in Benchmarks.

The browser diversion tax

Reusing the browser’s encoder and shipping the tapped frames over QUIC instead of native SRTP/UDP is not free, but it is close to it. In the localhost diversion prototype, the JS-layer round trip measured 1.20 ms over QUIC versus 0.84 ms for raw WebRTC SRTP/UDP — a +0.36 ms tax for the tap and the QUIC hop. That is noise next to a single Opus frame, and it buys you a single :443 plane, no SFU, and encoded-frame E2EE readiness.

Runtime: where the turn is actually spent

The runtime hop is the whole ballgame. Two shapes:
Three serial stages. The clock is:
  • ASR finalize — how long after end-of-speech the transcriber emits a final. Streaming ASR overlaps most of this with the user still talking.
  • LLM time-to-first-token — usually the single largest contributor, and the one you tune with model choice, prompt size, and self-hosted inference.
  • TTS time-to-first-audio — how fast the first synthesized frame comes back; streaming TTS starts speaking before the sentence is done.
You do not pay all three end-to-end — the stages pipeline — but first audio can’t leave until ASR has finalized and the LLM has produced enough token for TTS to start.

The hidden hop: endpointing

Before any of the five hops runs, the turn detector has to decide the user stopped. That decision has a cost, and it is real latency the caller feels:
  • silence_threshold_ms — how long a pause must last before it counts as end-of-turn. Lower it and you respond faster but cut people off mid-thought; raise it and the agent feels sluggish. This is the single biggest knob you own.
  • Hold-and-confirm barge-in — an onset arms a pending barge that only fires if speech sustains past a short window (~300 ms), so a backchannel (“mm-hm”) doesn’t cancel the agent. It trades a little barge-in latency for not talking over the caller.
Tune these in Turn detection; just know that a “slow agent” complaint is often an endpointing setting, not a transport or model problem.

Measure your own turn

Do not trust our numbers — instrument yours. Turn latency is a client-observable quantity: you have both timestamps, so you can compute it without any server-side access.
1

Stamp end-of-speech

Record the wall-clock time when your turn detector commits the turn (the Commit decision, or the provider’s server-VAD end-of-turn signal). This is t0.
2

Stamp first audio-out

Record the arrival time of the first downlink audio frame on voice/<sid>/downlink — the SDK hands you each frame. This is t1. Turn latency = t1 − t0. Log it per turn and take p50/p95/p99 over a call; a single number lies.
3

Split transport out

Read per-connection RTT and congestion window from the QUIC transport telemetry the platform exports to your analytics. If turn latency drifts up but RTT is flat, the regression is in the runtime, not the network.
4

Split the runtime stages

The agent runtime emits per-node timings — ASR finalize, LLM time-to-first-token, TTS time-to-first-audio — as tracing spans. Subtract them from your t1 − t0 and the remainder is capture + transport + egress.
There is no packaged “turn-latency” dashboard panel today. You assemble the view from the three signals above: client-side t1 − t0, exported transport RTT, and runtime node spans. The quality dashboards that do ship — MOS, jitter & loss — measure media quality, not turn latency; they are complementary, not a substitute.

When the number is too high

SymptomLikely causeFix
Agent feels sluggish, RTT is flatEndpointing window too longLower silence_threshold_ms; verify with t1 − t0
Turn latency high, runtime spans smallTransport RTT/lossCheck QUIC RTT/cwnd; confirm UDP/:443 reachable, no TCP-proxy fallback
First token slow, everything else fineLLM time-to-first-tokenSmaller/warm model; trim prompt; self-hosted inference
Long tail (p99 ≫ p50), p50 fineHead-of-line blocking on a TCP pathEnsure the QUIC/WebTransport rung is in use, not a WS/TCP fallback
Agent talks over the callerBarge-in confirm too aggressiveRaise the hold-and-confirm window; see barge-in debugging
The full runbook is in High latency.

High latency runbook

Step-by-step diagnosis when turn latency is too high.

MOS, jitter & loss

Media-quality metrics — separate from turn latency, and how to read them.

Call traces

Follow a single call end to end across every hop.

Turn detection

Endpointing and barge-in — the knobs that shape the hidden hop.

Runtime overview

Cascaded vs speech-to-speech — the hop that dominates the turn.

Benchmarks

How the stack compares on latency, cost, and scale.