skip to content

What does the Total Blocking Time (TBT) metric measure about a page load, how is its value computed, and why do lab tools use it as a stand-in for a field responsiveness metric they cannot measure?

level: middleimportance: should knowfreq 48%

answer

  1. only the time past fifty milliseconds
  2. sums long tasks, not all tasks
  3. measures the cause, not the interaction
  4. lab has no user to tap
  5. covers load only, not the visit

basics

~20 s

Total Blocking Time sums the blocking portion of every long task during load — the milliseconds each task runs beyond 50ms. It estimates how unresponsive the page would have been to input, which lab tools use as a proxy because no synthetic run has real user interactions to measure.

solid answer

~50 s

TBT measures how much of the loading period the main thread was blocked long enough to delay input. The browser calls any main-thread task over 50ms a **long task**; TBT takes each long task in the measurement window, subtracts the 50ms allowance, and sums what is left. Three tasks of 90ms, 60ms and 200ms contribute 40 + 10 + 150 = 200ms of TBT. The reason lab tools lean on it so heavily is that responsiveness in the field, Interaction to Next Paint, is measured from actual interactions — and a synthetic run has no user, so INP simply cannot be produced. TBT measures the *cause* instead of the effect: if the thread is busy for long stretches, any tap arriving in one of those stretches waits. It is a good directional proxy and a poor absolute one, because it only covers page load and it weights blocking that no user ever collided with exactly the same as blocking they did.

code

javascript · 12 lines
javascript
// Given the long tasks observed during a page load,
// TBT is the sum of each task's time beyond the 50ms allowance.
const LONG_TASK_THRESHOLD = 50;

const taskDurations = [90, 42, 60, 200, 51];

const tbt = taskDurations.reduce(
  (sum, duration) => sum + Math.max(0, duration - LONG_TASK_THRESHOLD),
  0
);

console.log(tbt); // 201  ->  40 + 0 + 10 + 150 + 1

go deeper

for a junior

Know that a main-thread task over 50ms is called a long task, and that TBT adds up how far past that threshold those tasks ran during page load.

for a middle

Be able to compute TBT from a list of task durations and explain the 50ms subtraction, including why splitting one long task into several short ones removes its contribution entirely.

for a senior

Explain why lab tools need a proxy at all, and where the proxy misleads: load-only scope, device throttling assumptions, and an aggregate standing in for what is effectively a worst case in the field.

for a principal

Own the policy question of what a synthetic score is allowed to gate. Be ready to argue when optimizing a proxy metric stops producing real user benefit and where field data should override it.

## Long tasks, and the 50ms allowance A browser's main thread runs work as a queue of tasks, and while one task runs, nothing else on that thread happens — including handling a tap or a click. A task that runs longer than **50 milliseconds** is called a *long task*. The 50ms figure is a convention: it is the point past which a newly arrived input is likely to feel delayed rather than instant. TBT is built directly on that definition. For each long task in the window, its **blocking time** is everything beyond the 50ms allowance: ```js // blocking time contributed by one task const blocking = Math.max(0, taskDuration - 50); // TBT over a load const tbt = tasks.reduce((sum, t) => sum + Math.max(0, t.duration - 50), 0); ``` A 51ms task contributes 1ms. A 300ms task contributes 250ms. Tasks under 50ms contribute nothing at all, which is the key structural property of the metric: **it does not care how many tasks you run, only how long individual ones are.** Splitting one 300ms task into six 50ms tasks drops its TBT contribution from 250ms to zero, even though the total work is identical. Lab tools measure TBT over the loading window — conventionally between First Contentful Paint and the point where the main thread goes reliably quiet — not over the entire session. ## Why the proxy exists at all The field metric for responsiveness, Interaction to Next Paint, is derived from real interactions: someone taps, and the browser measures how long until the next frame reflects it. That definition has a hard consequence — **if nobody interacts, there is no value**. A synthetic run in a lab tool loads the page with no user attached, so INP is not merely inconvenient to compute there; it does not exist. TBT resolves this by measuring the *condition* rather than the *symptom*. It cannot know whether a tap collided with a long task, but it can say precisely how much of the load period was spent in a state where a tap *would* have been delayed. Empirically the two correlate well: pages that ship a lot of blocking JavaScript during load tend to have poor field responsiveness, and driving TBT down usually moves the field metric in the same direction. ## Where the proxy breaks down An interviewer is usually probing for the limits, not the definition: - **TBT only covers load.** Field responsiveness is measured across the whole visit, including interactions ten minutes in. A page with a clean load and one catastrophically expensive filter handler can have near-zero TBT and terrible real-world responsiveness. - **TBT does not know where the user was.** Blocking during a phase where nobody could have interacted counts the same as blocking during the moment the user reached for the button. - **TBT is an aggregate, the field metric is roughly a worst case.** INP reports one bad interaction from the visit; TBT sums many. A page with one dreadful task and a page with many mediocre ones can report the same TBT and behave very differently. - **Lab conditions are chosen, not observed.** TBT depends heavily on the CPU throttling and device class the run simulates. The same page will produce wildly different TBT on an unthrottled desktop run and a simulated mid-tier phone — and the second is closer to what most users actually experience. ## Reading a TBT number Common lab guidance treats TBT under about 200ms as good and over about 600ms as poor on a simulated mobile run, and TBT carries the single largest weight in Lighthouse's composite performance score. Two consequences follow. First, TBT is often the metric that most moves a synthetic score, which makes it a magnet for optimization that does not always help users. Second, an unthrottled run flatters TBT badly enough that a page can be green in the lab and poor in the field — a reason to trust the field responsiveness data whenever you have it, and to treat TBT as the diagnostic that tells you *which* script is responsible. ## What TBT is good for Use it as a localizer, not as a goal. A high TBT during load tells you the main thread is being monopolized while the page is coming up, and the accompanying task breakdown names the script doing it — usually a large framework bundle evaluating, a heavy hydration pass, or a third-party tag executing on the main thread. That attribution is the value: it converts "the page feels sticky while loading" into "this 340ms task belongs to that file".

  • A page splits one 300ms task into six sequential 50ms tasks. What happens to TBT, and does the user's experience improve by the same amount?
    TBT drops from 250ms to zero, because tasks at or under the 50ms threshold contribute nothing. The experience does improve — an input arriving mid-sequence now waits at most one short task instead of up to 300ms — but not by the ratio the metric implies. The same total work still occupies the thread; the win is in worst-case wait, not in throughput.
  • Why can a page report near-zero TBT in a lab run and still have poor real-world responsiveness?
    Because TBT is scoped to the loading window and to the simulated device. An application whose load is clean but whose search filter blocks the thread for half a second on every keystroke will look perfect in a lab run that never types anything. Field responsiveness data covers the whole visit and would catch it.
  • Two pages report identical TBT of 600ms — one from a single 650ms task, one from twelve 100ms tasks. Which is likely to feel worse?
    The single long task, usually. An input arriving during it waits up to 650ms with no frame in between, which reads as a frozen page. With twelve shorter tasks the worst-case wait is around 100ms and the browser gets chances to paint between them. TBT sums identically, which is one of its known blind spots.

saying these in an interview costs you the question

  • Says TBT sums the full duration of every task
  • Counts tasks shorter than 50ms toward TBT
  • Claims INP can be measured in a synthetic lab run
  • Treats TBT as covering the whole user session
  • Assumes a green lab TBT guarantees good field responsiveness

context