skip to content

A page takes about four seconds before it is usable. Looking at a browser performance trace of that load, how do you tell whether the main thread was busy or sitting idle waiting on the network, and how does the answer change which fix you reach for?

level: middleimportance: must knowfreq 56%

answer

  1. two tracks, one question
  2. busy or idle?
  3. main-thread work against request bars
  4. alternating bursts look like stairs

basics

~20 s

Compare the main-thread track with the network track: solid scripting blocks mean the CPU is the bottleneck, while an idle main thread under a long request bar means you are waiting on bytes. Each points at a different family of fixes.

solid answer

~60 s

I read the two tracks against each other over the span in question. If the main thread is packed with scripting and rendering work, the page is CPU-bound: the fix family is doing less JavaScript at that moment — deferring, splitting, removing, or moving work off the critical path. If the main thread is largely empty while a request bar stretches across the same period, the page is network-bound, and the fix family is about requests: start them earlier, make them fewer, or make them smaller. The third and most common shape is a staircase — short bursts of work, each ending with a new request, each request followed by another burst. That is a dependency chain, and neither "optimize the script" nor "shrink the payload" fixes it; you have to break the chain so the discoveries happen in parallel. I also check a single request bar's own shape, because time spent before the first byte arrives is a server or connection problem, while a long download portion is a payload-size problem.

go deeper

for a junior

Know that a performance trace shows main-thread work and network requests on separate tracks, and that an empty main thread means the page is waiting rather than computing.

for a middle

Explain how you line the two tracks up, name the three shapes — CPU-bound, network-bound and chained — and say which family of fixes each one implies.

for a senior

Show you can act on the distinction: read a request bar's pre-first-byte portion versus its download portion, recognize a dependency chain that no single-item metric flags, and hand a server-side delay to the right owner instead of optimizing around it.

for a principal

Own the framing that the diagnosis depends on the conditions profiled, and decide which device and network profile the organization optimizes for when the two answers conflict.

## Two very different four-second pages "Four seconds to usable" describes at least two unrelated illnesses. In one, the CPU never stops: scripts parse, compile, execute, and the browser recalculates style and lays out repeatedly. In the other, the CPU is idle almost the whole time and the browser is simply waiting for bytes to arrive. Prescribing the wrong medicine is the classic wasted sprint — code-splitting a page that was blocked on a slow API, or adding preconnect hints to a page that was choking on a megabyte of script execution. The trace answers the question directly, and separating the two is the single highest-value read in a profiling session. ## What each track shows - **The main-thread track** is a timeline of tasks. Solid, coloured blocks mean the thread was executing something; gaps mean it had nothing to do. Categories are colour-coded — script evaluation, style and layout, paint — and long tasks (conventionally, anything over 50 ms) are flagged so they are easy to spot. - **The network track** draws one bar per request, positioned by when it started and how long it took. A request bar is internally divided: a leading portion covering queueing, connection setup and waiting for the server's first byte, then the portion where the response body is actually downloading. Reading them together turns "the page is slow" into a mechanism. ## The three shapes you will see **CPU-bound.** The main-thread track is a near-continuous wall of work; the network finished early or is irrelevant to the span. This says the page is doing too much computing at the wrong moment. The remedies are all forms of *less work now*: ship less script to this route, defer non-essential initialization, remove or delay third-party execution, hoist repeated computation out of loops, or move genuinely heavy computation off the main thread. **Network-bound.** The main thread has long empty gaps that line up with one or a few long request bars. The page is not slow because of your code; it is slow because a byte has not arrived. Remedies are about the requests themselves: start the critical ones earlier, reduce how many are required before the page is usable, shrink them, or improve where they are served from. If the bar's *leading* portion dominates — a long stretch before any body bytes — the delay is on the server or in connection setup, and no amount of client optimization touches it. **Chained (the staircase).** Short bursts of main-thread work alternating with idle gaps, where each burst ends by kicking off the next request. This is a dependency chain: HTML is parsed, which discovers a stylesheet, whose parsing discovers a font, which the layout needs, and so on. The total is not one slow thing — it is the *serialization* of several fast things. Measured naively, no single item looks bad, which is why teams miss it. The fix is structural: make the discoveries happen sooner and in parallel rather than one after another, so the chain becomes a wide shallow tree. ## Why the distinction decides the fix Each diagnosis has a completely different lever, and each lever is useless against the other illness: | Trace shape | Bottleneck | Family of fixes | | --- | --- | --- | | Solid main-thread work | CPU on the device | Do less, later, or elsewhere | | Idle thread, long request | Bytes and latency | Fewer, earlier, smaller requests | | Alternating bursts and gaps | Dependency chain | Parallelize discovery; shorten the chain | It also decides *who* you talk to next. A long pre-first-byte segment is a conversation with whoever owns the server or the edge, not a frontend task at all. A wall of scripting is a conversation about what the page is loading and why. ## Traps worth naming - **The answer changes with conditions.** The very same page is often network-bound on a slow connection and CPU-bound on a slow phone. That is not a contradiction; it means you must state which condition you profiled under and, if the audience spans both, profile both. - **Warm cache flips the picture.** A repeat visit with a warm cache can look CPU-bound simply because the network cost has vanished, hiding a first-visit download problem entirely. - **Idle does not always mean network.** Gaps can also be the browser doing work off the main thread, or genuine waiting on something other than a request. Confirm the gap actually lines up with a request bar before calling it network-bound. - **Both can be true.** Plenty of slow pages are network-bound in their first second and CPU-bound in the next. Split the span, diagnose each part separately, and fix the one that dominates first.

  • You see a two-second gap on the main thread that does not line up with any request bar. What might explain it?
    Not every wait is a fetch. The gap may be the browser doing work you do not see on that track, waiting on something the page asked for that is not an HTTP request, or simply the recording capturing a period where nothing was scheduled — for instance the user had not interacted yet. Widen the recorded range, check other tracks, and confirm what the page was actually waiting for before calling it a network problem.
  • A single request bar spends most of its length before any response bytes appear. What does that point at?
    Time before the first byte is queueing, connection setup and the server producing the response — not payload size. Shrinking the response will barely help. Look at where the request is served from, whether a connection had to be established first, and whether the server work itself is slow. It is often a backend or edge-placement conversation rather than a frontend fix.
  • Why can the same page be diagnosed as network-bound one day and CPU-bound the next?
    Because the diagnosis is relative to the conditions you recorded. On a fast device with a slow connection the network dominates; on a slow phone with good bandwidth the script execution dominates. Cache state moves it too — a warm-cache reload removes the download cost and makes the page look CPU-bound. Always state the device, network and cache conditions alongside the conclusion.

saying these in an interview costs you the question

  • Assumes any slow page load is a bundle-size problem
  • Reads an idle main thread as "nothing is happening"
  • Ignores the network track when the complaint is about JavaScript
  • Treats a request chain as one slow request
  • Draws a conclusion without saying what conditions were profiled

context