How TBT is calculated
A long task is any piece of main-thread work that runs for more than 50 ms. During that time the browser cannot handle a click or a keystroke. Only the excess over 50 ms counts as blocking: a 120 ms task adds 70 ms to TBT, while a 45 ms task adds nothing.
In the example below the tasks take 525 ms in total, but TBT is 330 ms. The single 300 ms task weighs the most, because the thread cannot respond to the user for its whole duration.
Task A: 120 ms → 120 − 50 = 70 ms
Task B: 45 ms → below threshold = 0 ms
Task C: 300 ms → 300 − 50 = 250 ms
Task D: 60 ms → 60 − 50 = 10 ms
───────────────────────────────────
TBT: 330 msLighthouse TBT thresholds
Since Lighthouse 10, TBT carries 30% of the Performance score, more than any other metric. LCP and CLS carry 25% each, FCP and Speed Index 10% each. That is why JavaScript work on the main thread has a large effect on the score.
web.dev recommends a TBT under 200 ms when tested on average mobile hardware.
| Device | Good | Needs improvement | Poor |
|---|---|---|---|
| Mobile | 0–200 ms | 200–600 ms | over 600 ms |
| Desktop | 0–150 ms | 150–350 ms | over 350 ms |
TBT, INP and Core Web Vitals
The Core Web Vitals are LCP, INP and CLS. TBT is not one of them, but it helps predict INP problems in the lab: the long tasks that inflate TBT also delay responses to clicks.
The two metrics measure different things. TBT covers page load up to TTI in a single controlled test. INP covers interactions throughout the visit, on real users’ devices. web.dev does not recommend measuring TBT in the field, because user interactions skew it. To judge responsiveness in the field, use INP from CrUX or your own RUM.
How to reduce TBT
- Break up long tasks. Yield to the main thread between chunks of work, for example with scheduler.yield() and a setTimeout() fallback.
- Ship less JavaScript. Remove unused code and split bundles so only what is needed runs at startup.
- Limit and defer third-party scripts. Ad tags, chat widgets and embeds often add long tasks of their own.
- Simplify expensive code, for example by narrowing selectors so a script does not walk thousands of DOM nodes.
- Do not rely on minification alone. It reduces the bytes transferred but does not remove script work. TBT drops when less code runs on the main thread, or runs in shorter chunks.
function yieldToMain() {
if (globalThis.scheduler?.yield) {
return scheduler.yield();
}
return new Promise((resolve) => setTimeout(resolve, 0));
}
async function processItems(items) {
for (const item of items) {
processItem(item);
// The browser can now handle a pending click
await yieldToMain();
}
}How to measure TBT
Run Lighthouse in Chrome DevTools or PageSpeed Insights and read TBT in the metrics section. Compare several runs on the same device profile, because a single test fluctuates. The DevTools Performance panel shows the individual long tasks, which makes it easy to find the script blocking the thread.
Total Blocking Time (TBT) is a lab metric that adds up main-thread blocking time between FCP and TTI. Only the excess over 50 ms in each long task counts. The higher the TBT, the longer the page could not respond to the user during the test.
Under Lighthouse thresholds a good TBT is 0–200 ms on mobile and 0–150 ms on desktop. Lighthouse rates more than 600 ms on mobile or 350 ms on desktop as poor.
No. The Core Web Vitals are LCP, INP and CLS. TBT is a lab metric that Lighthouse includes in the Performance score with a 30% weight. In the lab it serves as a proxy for INP.
TBT measures main-thread blocking during load in a controlled test with no real interactions. INP measures how quickly the page responds to clicks, taps and key presses throughout real users’ visits. TBT helps find causes; INP shows the effect in the field.
The lab test stops measuring TBT once the page has loaded, while INP also covers later interactions such as opening filters or a cart. Real users also have slower devices than the test profile. Find the slow interactions in RUM data or the Performance panel.
Break up long tasks by yielding to the browser, remove unused JavaScript and split bundles, limit third-party scripts and simplify expensive code. After each change, compare several Lighthouse runs on the same device profile.