Time to Interactive (TTI) marks the point when the page has rendered, event handlers are registered, and the main thread has been quiet enough, with no long tasks for five seconds, to respond to input reliably. It answers “when can the visitor actually use this?” rather than “when does it look done?”.
Retired from the score, still on the report
Lighthouse 10 removed TTI from the Performance score in 2023 because it was noisy and easily skewed by a single late task. Total Blocking Time took over as the load-responsiveness signal, and the field metric INP now measures real responsiveness directly. TTI still appears as a diagnostic and in older reports, so it is worth being able to read.
Why we still print it
Our before/after videos carry two numbers on each panel: “Loaded”, which is Speed Index, and “Usable”, which is TTI. Neither label is a technical term, and that is the point of the choice. The people who watch those videos are deciding whether a page feels finished, and “usable at 3.1 s versus 9.4 s” answers that question in a way “TBT 180 ms” does not.
We keep TTI for legibility while scoring on TBT, and the two disagree often enough to be worth watching: deferring work lowers blocking time while pushing the quiet window later, so a page can improve on the metric Google scores and get worse on the one a viewer would recognise.
Wide bands, and why
The Good / Needs-work / Poor bands sit in the summary panel. TTI is a lab metric from a single simulated run under CPU throttling, with no field percentile. Because it depends on a five-second quiet window, one late task can push the figure out dramatically, which is exactly why it was retired in favour of TBT.
What delays interactivity
- Heavy JavaScript gating the page, which must download, parse and execute before anything responds.
- Long tasks during load, each one resetting the quiet window TTI waits for.
- Render-blocking resources in the
<head>, which delay the whole timeline and every downstream metric with it. - Shipping far more JavaScript than the first screen needs, loading widgets nobody has asked for yet.
The cost of loading on demand
- Code-splitting and deferring mean some features load on demand, so the first interaction with one is slower: an INP hit on first use.
- Over-deferring leaves the page looking ready before its handlers are wired up, so it feels interactive and is not.
We load deferred behaviour on the first real interaction rather than pre-loading it up front, which trades a few milliseconds on first use for a thread that stays free during load.
Cutting the gate, in code
- <script src="/app.js"></script>
+ <script src="/app.js" defer></script>
Then load heavy, non-critical widgets only when they are actually needed:
button.addEventListener('click', () => import('/chat-widget.js'));
Why the same levers pull TTI in
The same levers that cut TBT pull TTI earlier: WebSpeed defers third-party scripts to the first interaction, delays non-critical inline scripts, and spreads jQuery startup work out, so the main thread settles sooner and the page becomes usable earlier.