The five hops
A turn walks the same path in both directions. The user’s audio goes capture → encode → transport → runtime. The reply comes back runtime → transport → egress. The table shows where the time goes and what dominates each hop.The runtime hop dominates the total by an order of magnitude. The transport
and codec hops are single- to low-double-digit milliseconds. A cascaded
ASR→LLM→TTS turn is hundreds of milliseconds. If you chase latency, start at
the runtime. Tune transport only after that. 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. The platform reuses it and does not replace it. A loopbackRTCPeerConnection 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 the
depth that 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 it to 8 kHz PCM16. 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 use
VAD-gating instead. This is a
correctness choice, not a latency choice.
Transport: QUIC earns its place here
This is the hop where our transport choice shows up as a number. We used a controlled prototype rig over a WAN link (50 ms RTT, ~1% loss). We measured the same turn — end-of-user-speech to start-of-agent-speech — over QUIC and over a TCP+TLS baseline:
QUIC roughly halves the turn. More important, QUIC keeps the tail flat.
The p99 sits right on the p50, because head-of-line blocking is gone. Under
concurrency (c = 20) the gap widens where it hurts most. Time-to-first-token
p50 is 93.9 ms vs 143.6 ms (−35%). The p99 is 149.2 ms vs 1197.9 ms,
an ~8× better tail. Throughput is ~60% higher.
The browser diversion tax
The platform reuses the browser’s encoder and ships the tapped frames over QUIC instead of native SRTP/UDP. This is not free, but it is close to free. In the localhost diversion prototype, the JS-layer round trip measured 1.20 ms over QUIC and 0.84 ms for raw WebRTC SRTP/UDP. The tap and the QUIC hop cost +0.36 ms. That is noise next to a single Opus frame. In exchange you get a single:443 plane, no SFU, and encoded-frame E2EE readiness.
Runtime: where the turn is actually spent
The runtime hop dominates the turn. There are two shapes:- Cascaded (ASR → LLM → TTS)
- Speech-to-speech (single model)
Three serial stages. The clock is:
- ASR finalize. How long after end-of-speech the transcriber emits a final result. Streaming ASR overlaps most of this time while the user still talks.
- LLM time-to-first-token. Usually the single largest contributor. You tune it 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 to speak before the sentence is done.
The hidden hop: endpointing
Before any of the five hops runs, the turn detector must decide that the user stopped. That decision has a cost. It is real latency that the caller feels:silence_threshold_ms. How long a pause must last before it counts as end-of-turn. If you lower it, the agent responds faster but cuts people off mid-thought. If you raise it, the agent feels sluggish. This is the single biggest knob that you own.- Hold-and-confirm barge-in. A speech onset arms a pending barge. The barge fires only if speech continues past a short window (~300 ms). Thus a backchannel (“mm-hm”) does not cancel the agent. This trades a little barge-in latency for an agent that does not talk over the caller.
Measure your own turn
Do not trust our numbers. Instrument yours. Turn latency is a client-observable quantity. You have both timestamps. Thus 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. Take p50/p95/p99 over a
call. A single number lies.3
Split transport out
Read the per-connection RTT and congestion window from the QUIC
transport telemetry that 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 as tracing spans: ASR finalize,
LLM time-to-first-token, and TTS time-to-first-audio. Subtract them from
your
t1 − t0. 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 complement each other. They are
not substitutes.When the number is too high
The full runbook is in
High latency.
Related
High latency runbook
Step-by-step diagnosis when turn latency is too high.
MOS, jitter & loss
Media-quality metrics. They are separate from turn latency. The page
tells you 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.

