busy-lunch-15701
03/06/2026, 2:03 PMThat is a fantastic question. The formula in the LiveKit docs is an idealized, theoretical minimum.
The docs say total_latency = eou.end_of_utterance_delay + llm.ttft + tts.ttfb.
This formula mathematically assumes a perfectly instantaneous, zero-latency pipeline where:
The LLM provider (like OpenAI) receives your prompt on the exact same millisecond that the LiveKit VAD finishes end_of_utterance_delay.
The TTS provider (like ElevenLabs) receives your text on the exact same millisecond that the LLM emits its very first token (ttft).
In a perfect world with zero network overhead, zero queueing, and perfect streaming (sending word-by-word instead of waiting for a full sentence), that formula is 100% correct.
But the raw UNIX timestamps prove reality is messier:
If that formula were perfectly true in reality, the tts_node starting time would equal the LLM First Token time.
But as your own data proved in Turn #3:
LLM First Token arrived at .286s
TTS didn't start until .548s
That is over 250ms of "hidden" latency that the LiveKit docs equation completely ignores! It ignores it because it assumes your server teleported the LLM token instantly to the TTS server. In reality, your server had to parse the token, realize it was the end of a sentence, construct an HTTP payload, and wait for the TLS handshake with the TTS provider.
Conclusion: The LiveKit docs formula is what they want the latency to be. It is useful for marketing and rough budgeting.
But your Gantt chart is using absolute UNIX clocks. It is showing you what the latency actually is on the wire. If you want to optimize your user experience, the Gantt chart (and the 6.42s total time) is the truth you should optimize against, because that's exactly how long the caller was sitting in silence waiting for audio!tall-airline-16756
03/06/2026, 2:04 PMtall-airline-16756
03/06/2026, 2:04 PMbusy-lunch-15701
03/06/2026, 4:03 PMEOUMetric.end_of_utterance_delay included EOUMetric.on_user_turn_completed_delay ?tall-airline-16756
03/06/2026, 4:03 PMEOUMetrics.end_of_utterance_delay does not include on_user_turn_completed time (and there is no documented metric named on_user_turn_completed_delay).
Quick breakdown:
• EOUMetrics.end_of_utterance_delay measures the time from when the user stops speaking to when end‑of‑utterance (EOU) detection fires. It covers VAD silence timing and any turn‑detection model adjustments.
• on_user_turn_completed is a pipeline lifecycle hook that runs after EOU detection. Any processing you do inside that hook (parsing tokens, creating requests, queuing work, etc.) happens after end_of_utterance_delay has already been recorded.
• Because there is no on_user_turn_completed_delay metric built into LiveKit, that post‑EOU work is not included in end_of_utterance_delay. You’ll need to instrument and emit additional metrics/events if you want that interval captured in your Gantt/dashboard.
If you want, I can suggest specific metric/event names and where to emit them so your dashboard shows:
• time from EOU detection → on_user_turn_completed start
• on_user_turn_completed processing duration
• time from LLM first token → TTS initiation
Which of those would you like to add first?
Sources: STT Metrics | LiveKit Documentation | examples/voice_agents | livekit/livekit_composite | DeepWiki | Pipeline nodes and hooks | LiveKit Documentationbusy-lunch-15701
03/06/2026, 4:06 PMEOUMetric.on_user_turn_completed_delay . It sits in your doc https://docs.livekit.io/deploy/observability/data/#end-of-utterance-eou-tall-airline-16756
03/06/2026, 4:06 PMEOUMetric.on_user_turn_completed_delay is listed in the LiveKit observability docs. To be clear:
• They are separate metrics.
EOUMetric.end_of_utterance_delay measures the time from when the user stops speaking until the EOU detection fires (VAD/turn detection). EOUMetric.on_user_turn_completed_delay measures the time associated with the on_user_turn_completed lifecycle step — i.e., the processing that happens after EOU detection completes.
• end_of_utterance_delay does not include on_user_turn_completed_delay.
end_of_utterance_delay ends when EOU is detected. on_user_turn_completed_delay captures the subsequent work (your agent’s post‑EOU processing). If you want full end‑to‑end attribution, you need to sum or correlate these metrics in your dashboard.
What I recommend for your Gantt/dashboard
• Show both metrics as separate segments so you can see:
◦ EOU detection latency (end_of_utterance_delay)
◦ Post‑EOU processing latency (on_user_turn_completed_delay)
• Add explicit markers for when LLM first token arrives and when TTS is initiated so you can observe the gaps between these stages.
• Correlate using synchronized timestamps (NTP or server timestamps) so the sums are accurate.
If you’d like, share a sample trace (Turn #3 timestamps) and I’ll point out exactly which spans correspond to these metrics and which optimizations would reduce the biggest gaps. Which trace would you like me to look at?
Sources: STT Metrics | LiveKit Documentation | Pipeline nodes and hooks | LiveKit Documentationbusy-lunch-15701
03/06/2026, 4:08 PMEOUMetric.on_user_turn_completed_delay runs sync right before LLM node? Or it run async, parrallel with LLM node?tall-airline-16756
03/06/2026, 4:09 PMEOUMetric.on_user_turn_completed_delay runs synchronously immediately before the LLM node or if it runs asynchronously/parallel with the LLM node.
Short answer
• EOUMetric.on_user_turn_completed_delay runs synchronously and represents pre-LLM processing.
• It runs before the LLM node begins; it does not run in parallel with LLM inference.
Why
• End‑of‑utterance detection triggers the end of the user turn, then the on_user_turn_completed lifecycle hook is invoked. Any work done in that hook (context augmentation, RAG lookups, modifications to ChatContext, etc.) is executed before the agent proceeds to the LLM node.
• Because those changes must be applied to the conversation state prior to calling the LLM, the pipeline waits for on_user_turn_completed to finish. That makes on_user_turn_completed_delay part of the pre‑inference latency (it blocks the pipeline until complete).
What that means for your dashboard
• Treat on_user_turn_completed_delay as a sequential span that precedes LLM TTFT. Sum it with other preprocessing delays when attributing end‑to‑end latency.
• If you want to verify behavior in traces, instrument and display:
◦ EOU detection → end_of_utterance_delay
◦ on_user_turn_completed start → on_user_turn_completed_delay
◦ LLM request start → llm.ttft (first token)
◦ TTS initiation → tts.ttfb
This will make the scheduling and bottlenecks explicit.
If you’d like, paste a short trace (timestamps for EOU detection, on_user_turn_completed start/end, LLM request start, first token) and I’ll map the spans and point out which stage to optimize first.
Sources: How does end-of-utterance detection work in conversations? | Pipeline nodes and hooks | LiveKit Documentation | External data and RAG | LiveKit Documentation | LLM Metrics | LiveKit Documentationbusy-lunch-15701
03/06/2026, 4:11 PMtotal_latency = eou.end_of_utterance_delay + llm.ttft + tts.ttfb
is invalid.
it should've been
total_latency = eou.end_of_utterance_delay + eou.on_user_turn_completed_delay + llm.ttft + tts.ttfbtall-airline-16756
03/06/2026, 4:11 PMtotal_latency = eou.end_of_utterance_delay + llm.ttft + tts.ttfb
is a lower‑bound / best‑case estimate that captures core service latencies.
• For observed, wall‑clock end‑to‑end latency you should include the post‑EOU processing:
total_latency = eou.end_of_utterance_delay + eou.on_user_turn_completed_delay + llm.ttft + tts.ttfb
on_user_turn_completed_delay is synchronous pre‑LLM work and therefore adds to the user‑facing wait time.
Why this matters
• end_of_utterance_delay finishes when EOU detection fires. on_user_turn_completed_delay covers the subsequent processing (context augmentation, RAG lookups, preparing the LLM prompt) that must complete before the LLM is invoked.
• Those processing steps block the pipeline, so excluding them underestimates the true silence/latency the caller experiences.
Practical tips for your dashboard
• Display end_of_utterance_delay and on_user_turn_completed_delay as separate Gantt segments (so you can see if preprocessing or EOU detection is the bottleneck).
• Correlate LLM and TTS events with those segments (LLM request start, LLM first token, TTS request start, TTS first byte).
• Ensure clock sync across services so sums match observed wall‑clock times.
• If you want finer attribution, add metrics for agent_processing_delay, tts_initiation_delay, and network/handshake times.
If you’d like, paste one trace (timestamps for EOU detect, on_user_turn_completed start/end, LLM request start, first token, TTS start) and I’ll map the spans and show exactly where time is being spent and which optimizations will matter most.