The 50 millisecond rule
A browser runs JavaScript, layout and painting on one main thread. A task shorter than 50 ms feels instant, because the browser can respond to a tap right after. Any time a task runs beyond 50 ms, a tap would have had to wait. TBT adds up those overruns, which is why splitting work into small chunks lowers it even when the total work stays the same.
Split the long tasks
Total Blocking Time: 650 ms → Poor (mobile Lighthouse scale)
Grey = the first 50 ms of each task (allowed). Magenta = the part over 50 ms, which is what TBT adds up. Same total work, but split into short tasks, almost none of it blocks.
How to reduce Total Blocking Time
- Ship less JavaScript: remove unused dependencies, and use code splitting so each route loads only what it needs.
- Defer third parties: chat widgets, A/B testing, heatmaps and ad scripts are frequent culprits. Load them after the page is interactive, or on user action.
- Hydrate less: server-rendered pages that re-run the whole app on the client can create one huge task. Islands or partial hydration help.
- Yield in long loops: process data in batches and
await scheduler.yield()between them. - Move work off the main thread: a Web Worker can handle parsing, sorting and other number-crunching.
TBT is lab-only. Its real-world counterpart is Interaction to Next Paint, which covers interactions for the whole visit, not just the load.