Total Blocking Time

Total Blocking Time (TBT) measures how responsive your site is to user input. Long-running CPU tasks block the page main thread, and the work required to respond to user interaction can't happen right away.

JavaScript execution is the most common type of long-running CPU task, but parsing HTML or updating the page layout can also block user interaction.

TBT makes up 25% of the overall Lighthouse Performance score. It's often used as an alternative to First Input Delay when running lab-based tests.

How is Total Blocking Time defined?

Total Blocking Time measures the amount of time where a CPU task is taking longer than 50ms to finish. For example, if a task takes 120ms that will add 70ms to overall TBT.

Long CPU tasks before the First Contentful Paint don't count as blocking, since without a visible user interface there's no user interaction that would be blocked.

This picture shows an example main thread timeline. To show how blocking time affects user experience, the picture also shows a user clicking on a button, and when that click event is handled.

Slow Total Blocking Time example

Because of the long main thread tasks, the page takes a long time to respond to user input. The time it takes to respond to user input is called First Input Delay. We'll look at how that metric relates to TBT further down in this article.

Several shorter CPU tasks have a smaller impact on the user experience. Tasks under 50ms do not increase Total Blocking Time. That means TBT better captures user impact than looking at the total main thread CPU time.

Fast Total Blocking Time example

What's a good Total Blocking Time

Ideally, TBT should be under 300ms on mobile and under 100ms on desktop. Total Blocking Time determines 25% of the overall Lighthouse Performance score.

LCP subscore Max TTB (Mobile) Max TTB (Desktop)
100 0.1s 0.05s
90 0.3s 0.1s
50 0.6s 0.3s
10 1.2s 0.8s

Total Blocking Time vs First Input Delay

First Input Delay can only be measured if the user interacts with the page. Synthetic performance tools like Lighthouse don't involve any user interaction, and therefore use Total Blocking Time as a proxy metric.

First Input Delay also depends on the type of user input that's made, for example what button the user decided to click on. So an increase in FID could mean there was a code change that made the site slower, but it could also mean users are increasingly using a slower feature.

User input delays are larger when the main thread is blocked. Therefore a high TBT value means there are many times during the page load process where the page would respond slowly if the user tried to interact with it.

How to optimize Total Blocking Time

Identify the cause of CPU activity

Look at a CPU timeline recording, for example in Chrome DevTools. What parts of your code are causing the long tasks?

Review third-party scripts

Third-party code like chat widgets or A/B testing tools can add a large amount of CPU processing to your page. Consider if some of them can be removed, or if they can be lazy loaded when they are needed.

Split up long tasks

Instead of running all JavaScript updates in one, consider doing the work in stages.

For example, if you're rendering a chart and a map, you could first render the chart and then wait 50ms before rendering the map. This way user input can be handled in the gap between the two rendering steps, and the page stays responsive throughout.

Speed up your code

One way to reduce blocking time is to make your JavaScript code run faster. This will not only improve TBT, but also make your page load faster in general.

Long Tasks and Total Blocking Time in Chrome DevTools

Create a recording in the Chrome DevTools Performance tab to view long tasks and Total Blocking Time.

Long tasks are marked by a triangle in the top right corner of the task marker. Blocking time is indicated using red stripes.

Total Blocking Time in Chrome DevTools

You can find the Total Blocking Time for the page in the bottom right corner.

Click on each task to view what code caused it to take a long time.

Total Blocking Time in Lighthouse

TBT is one of the main metrics shown at the top of each Lighthouse report. You can run Lighthouse on web.dev, or in the DevTools Lighthouse tab. On web.dev you'll need to click View report to see the full test result.

Total Blocking Time metric in Lighthouse

Each Lighthouse report also includes a list of long tasks, and what source file they can be attributed to.

Long Tasks in Lighthouse

Total Blocking Time in DebugBear

You can find a chart of TBT over time on the Overview and Performance tabs.

DebugBear TBT chart

The CPU timeline can help identify specific long tasks.

DebugBear CPU timeline

You can also find the full Lighthouse report in the Lighthouse tab.

Long Tasks API

The Long Tasks API allows you to access long tasks from JavaScript running on the page.

Here's how you can calculate total blocking time:

var totalBlockingTime = 0;
var observer = new PerformanceObserver(function (list) {
  let perfEntries = list.getEntries();
  for (const perfEntry of perfEntries) {
    totalBlockingTime += perfEntry.duration - 50;
  }
  console.log({ totalBlockingTime });
});
observer.observe({ type: "longtask", buffered: true });

The console output will show the blocking time in milliseconds. (If buffered: true isn't working for you, try using a newer version of Chrome. Chrome 90 always works for me.)

{ totalBlockingTime: 317 }

You can use this to capture real-user metrics about your page.

The full performance entry data looks something like this.

[
  {
    "name": "self",
    "entryType": "longtask",
    "startTime": 826.6750000184402,
    "duration": 115,
    "attribution": [
      {
        "name": "unknown",
        "entryType": "taskattribution",
        "startTime": 0,
        "duration": 0,
        "containerType": "window",
        "containerSrc": "",
        "containerId": "",
        "containerName": ""
      }
    ]
  },
  {
    "name": "same-origin-descendant",
    "entryType": "longtask",
    "startTime": 17693651.6000001,
    "duration": 67,
    "attribution": [
      {
        "name": "unknown",
        "entryType": "taskattribution",
        "startTime": 0,
        "duration": 0,
        "containerType": "iframe",
        "containerSrc": "",
        "containerId": "intercom-frame",
        "containerName": ""
      }
    ]
  }
]

Still need help? Contact matt@debugbear.com for support.
DebugBear is a website monitoring tool built for front-end teams. Track performance metrics and Lighthouse scores in CI and production. Learn more.