Learnbeginner

Understanding TBT: What Total Blocking Time Measures and Why It Matters

Learn what Total Blocking Time is, how it is calculated, why it carries 30% of the Lighthouse score, and how it connects to real-world user experience.

Rankwise Team·Updated Mar 12, 2026·6 min read

Total Blocking Time (TBT) is a lab performance metric that measures how long the browser's main thread is blocked by long-running JavaScript tasks during page load. It is the strongest lab predictor of whether real users will experience sluggish interactions, and it accounts for 30% of the Lighthouse performance score.


What TBT measures

The browser's main thread is responsible for executing JavaScript, calculating styles, performing layout, and painting pixels. It handles all of this sequentially — one task at a time. When a task takes longer than 50ms, the browser cannot respond to user input (clicks, taps, keystrokes) until that task finishes.

TBT sums up the "blocking portion" of every long task that occurs between two other metrics:

  • Start: First Contentful Paint (FCP) — when the first content appears
  • End: Time to Interactive (TTI) — when the page is reliably responsive

The calculation

For each task longer than 50ms, subtract 50ms. Add up the remainders.

Task A:  80ms → blocking time: 30ms  (80 - 50)
Task B:  40ms → blocking time:  0ms  (under 50ms threshold)
Task C: 200ms → blocking time: 150ms (200 - 50)
Task D:  60ms → blocking time: 10ms  (60 - 50)

TBT = 30 + 0 + 150 + 10 = 190ms

A TBT of 190ms means the main thread was unavailable for 190ms during the page load window. During those milliseconds, a user clicking a button would experience a delay.


Why 50ms is the threshold

The 50ms limit comes from human perception research. Users perceive delays under 50ms as instant. Between 50ms and 100ms, they notice a slight lag. Above 100ms, the interface feels sluggish. Above 300ms, it feels broken.

By counting only the portion of each task above 50ms, TBT focuses on the time that actually impacts perceived responsiveness.


TBT thresholds

RatingTBT valueWhat it means
GoodUnder 200msUsers can interact without noticeable delay
Needs improvement200ms – 600msSome interactions feel slow, especially on mobile
PoorOver 600msUsers experience significant lag; rage clicks likely

These thresholds apply to Lighthouse lab testing on simulated mobile devices with 4x CPU throttling.


TBT vs. FID vs. INP

Three metrics measure interactivity, each from a different angle:

MetricTypeWhat it measuresWhen it measures
TBTLabTotal blocking time during loadFCP → TTI
FIDField (deprecated)Delay of the first interactionFirst user input event
INPField (current)Delay of the worst interactionEntire page lifecycle

TBT and INP complement each other:

  • TBT catches interactivity problems during development (in CI, in Lighthouse audits) before users encounter them
  • INP reveals real-world interactivity problems that lab tests miss (runtime JavaScript, post-load interactions, real device constraints)

If TBT is good but INP is poor, the problem is likely post-load JavaScript (event handlers, dynamic content loading). If TBT is poor, fixing it will almost certainly improve INP as well.


What causes high TBT

1. Large JavaScript bundles

More JavaScript means more parsing and execution time on the main thread. A 500KB JavaScript bundle can take 200–400ms to parse and execute on a mid-range mobile device.

2. Synchronous initialization

Frameworks and applications that run all their setup code synchronously during page load create large monolithic tasks:

Framework init:     150ms ████████████████
State hydration:    100ms ██████████
Event binding:       80ms ████████
Total single task:  330ms → 280ms blocking time

3. Third-party scripts

Analytics tags, ad scripts, chat widgets, and A/B testing tools each add their own initialization tasks. Five third-party scripts adding 60ms each creates 50ms of total blocking time — and that assumes they do not trigger additional work.

4. Forced synchronous layout

JavaScript that alternates between reading and writing DOM properties forces the browser to recalculate layout on the main thread, creating long tasks that are not visible in the JavaScript profiler.

5. Heavy CSS processing

Pages with thousands of CSS rules or complex selectors require significant style recalculation time after the DOM changes, contributing to task length.


How TBT affects your Lighthouse score

TBT has the highest weight of any metric in the Lighthouse performance score:

MetricWeight
Total Blocking Time30%
Largest Contentful Paint25%
Cumulative Layout Shift25%
First Contentful Paint10%
Speed Index10%

This means TBT has more influence on your score than LCP or CLS individually. A page with perfect LCP and CLS but 800ms TBT will score poorly.


How to measure TBT

Lighthouse (CLI or DevTools)

npx lighthouse https://example.com --only-categories=performance --output=json | \
  python3 -c "import json,sys; d=json.load(sys.stdin); print('TBT:', d['audits']['total-blocking-time']['numericValue'], 'ms')"

Chrome DevTools Performance tab

Record a page load, then look at the "Total Blocking Time" metric in the summary. Click individual long tasks to see their source.

WebPageTest

WebPageTest reports TBT alongside a main thread breakdown that shows exactly which scripts and operations contribute to blocking time.

In code (approximation)

let estimatedTBT = 0

new PerformanceObserver(list => {
  for (const entry of list.getEntries()) {
    if (entry.duration > 50) {
      estimatedTBT += entry.duration - 50
    }
  }
}).observe({ type: "longtask", buffered: true })

// Check after page settles
setTimeout(() => {
  console.log("Estimated TBT:", estimatedTBT, "ms")
}, 10000)

Note: this gives an approximation. The Long Tasks API reports tasks over 50ms but with limited attribution detail compared to DevTools.


Quick wins for reducing TBT

  1. Defer third-party scripts — move analytics and widgets to load after the page is interactive
  2. Add defer or async to script tags that do not need to block rendering
  3. Code-split by route — ship only the JavaScript needed for the current page
  4. Remove unused JavaScript — audit your bundle and cut libraries that are not actively used
  5. Break up initialization — split large setup functions into smaller chunks with setTimeout(fn, 0) between them

For a deeper walkthrough, see the reducing blocking time guide and the JavaScript performance guide.


Frequently Asked Questions

Why is TBT a lab-only metric?

TBT requires knowing when Time to Interactive (TTI) occurs, which is only determinable after the page has fully settled. In real-world usage, this moment varies based on user behavior, network conditions, and background tabs. Lab environments provide the controlled conditions needed for a consistent TTI measurement.

Does TBT matter for SEO?

Indirectly. TBT itself is not a direct ranking signal, but it strongly correlates with INP, which is part of Core Web Vitals (a confirmed ranking signal). Improving TBT in the lab almost always improves INP in the field.

Can images cause high TBT?

Images do not directly cause TBT because they decode on separate threads. However, JavaScript that processes images (resizing, canvas operations, lazy-load observers firing for many images simultaneously) can create long tasks that increase TBT.

What is the difference between TBT and TTI?

TTI measures when the page becomes reliably interactive (a point in time). TBT measures how much blocking occurred before that point (a duration). A page can have a fast TTI but high TBT if it has many moderate-length long tasks that resolve before a quiet window appears.

Should I optimize TBT or INP first?

Start with TBT because it is measurable in CI and provides faster feedback loops. Once TBT is under 200ms, shift focus to INP to catch post-load interactivity issues that TBT does not measure.

Part of the SEO Fundamentals topic

Newsletter

Stay ahead of AI search

Weekly insights on GEO and content optimization.