A fast first token can coexist with a slow task when the user must wait for retrieval, tools, or validation before the output is useful. Measure the completion milestone that matters to the workflow and trace its dependencies.
Name the usable outcome
For a chat explanation, incremental text may already be useful. For a booking or account lookup, a friendly opening sentence is not the result. Define whether completion means a final answer, an authorized state change, a validated extraction, or a successful handoff.
Read the synthetic timeline
The fixture starts at zero, emits a token at 80 milliseconds, finishes the first tool at 600, finishes a dependent tool at 1,200, and validates the result at 1,500. Time to first token is 80, while useful completion takes 1,500. The difference is deliberate illustration, not a measured provider benchmark.
Optimize the actual dependency
- Record absolute milestones from the same request and clock domain where possible.
- Identify sequential operations on the critical path; do not sum overlapping spans as if all were sequential.
- Test concurrency only when operations are independent and permissions still apply.
- Re-evaluate complete-task correctness after caching, reducing output, or changing models.
Include canceled and failed tasks
Reporting completion latency only for successful fast cases hides timeouts and abandonment. Keep outcome counts alongside latency summaries and choose a consistent treatment of incomplete requests. A loading animation or earlier greeting may improve perceived responsiveness, but it does not shorten a required downstream operation.
Run the worked example
Save the synthetic Node.js example and run node investigate-first-token-versus-task-latency.mjs with Node.js 22 or newer. The assertions check the illustrated records and calculations; they do not test a deployed provider, SDK, or access control. No credentials or network connection are needed.
// Synthetic teaching fixture. No credentials, network calls, or production verification.
import assert from 'node:assert/strict';
const timeline = { started: 0, firstToken: 80, toolOneDone: 600, toolTwoDone: 1200, validated: 1500 };
const firstTokenMs = timeline.firstToken - timeline.started;
const usableTaskMs = timeline.validated - timeline.started;
assert.equal(firstTokenMs, 80);
assert.equal(usableTaskMs, 1500);
assert.ok(usableTaskMs > timeline.toolTwoDone);
console.log(JSON.stringify({ firstTokenMs, usableTaskMs, afterFirstTokenMs: usableTaskMs - firstTokenMs }));
References and further reading
Maintained by DriftRail. AI assisted the October 2026 content and template revision. Examples are illustrative; they are not measured product benchmarks. Suggest a correction.