The main thread
The browser’s main thread is the single thread that runs a page’s JavaScript, parses HTML/CSS, computes layout and style, and paints — and handles user input. Because one thread does all of it, work is serialized: while the main thread is busy running a script, it can’t respond to a click or paint the next frame. This is the execution-side counterpart to page-weight: page weight is what you download, the main thread is where what you downloaded gets run, and both gate how fast a page feels.
The two numbers that bound it
Per when-to-block-main-thread:
- ~16.6 ms — the budget for one frame at 60 fps. To stay smooth the main thread has to hand control back often enough to paint every frame; a task that runs longer makes the page drop frames (jank).
- 50 ms — the threshold above which a task is a “long task.” A long task is a stretch where the main thread is blocked and can’t service input, so any interaction that arrives during it waits.
Why it’s the binding constraint for apps
For static pages the limiting factor is transfer bytes; for interactive apps it shifts to main-thread execution, which is exactly what Interaction to Next Paint measures — an interaction’s input delay is largely time spent waiting for a busy main thread, and its processing duration is main-thread work. Long tasks are also what Total Blocking Time sums up (the 90th-pctile mobile TBT is 5,786 ms in the Almanac). So cutting bundle-size helps not just load but responsiveness, by giving the main thread less to run.
Blocking it isn’t always wrong
The standard advice is to move heavy work off the main thread onto a Web Worker. But
when-to-block-main-thread argues the rule is really don’t block it for too long: the worker boundary
has its own cost (the structured-clone copy on every postMessage), so for data-bound work
— a big payload with light processing — keeping the work on the main thread can be faster than paying to ship
it across. The discipline is to keep any single task short (or chunked/yielded), not to reflexively offload.
Blocking for ~1 second is even defensible on an explicitly user-invoked action that needs an immediate
result.
Related
inp · web-worker · when-to-block-main-thread · bundle-size · web-performance