skip to content

A team added fourteen <link rel="preload"> tags to a page's head so that "everything arrives sooner", and the page's Largest Contentful Paint got worse. Explain how over-preloading slows a page down, and how you would decide which preloads to keep.

level: seniorimportance: should knowfreq 44%

answer

  1. hints reorder, they do not add capacity
  2. the scanner already found most of them
  3. everything urgent means nothing is urgent
  4. late discovery is the only justification
  5. a fast laptop hides the contention

basics

~20 s

Preload is a mandatory high-priority fetch, so fourteen of them jump the queue ahead of the resources that determine first paint and share the same finite bandwidth. Keep only hints for critical resources the browser would otherwise discover late.

solid answer

~60 s

Preload does not create bandwidth; it reorders access to it. Each tag issues a mandatory fetch at a priority the browser derives from `as`, so fourteen of them start early and multiplex over the same connection as the stylesheet and the LCP image — every one of those requests now finishes later than it would have. Worse, most of them are usually redundant: the preload scanner already found the `<img>` and `<script>` tags in the markup, so those hints add contention and no discovery. The ones that actively hurt are for resources the first screen does not need — below-the-fold images, other routes' chunks — which are now competing with the thing the user is waiting for. My pass would be: keep a hint only if the resource is needed for the current viewport *and* the browser would find it late, meaning its URL is buried in CSS or produced by JavaScript. Everything else goes. Then I verify with a before-and-after comparison rather than trusting the reasoning, checking the waterfall for the LCP resource's start and finish times and watching field LCP after the change.

code

html · 7 lines
html
<!-- drop: the preload scanner finds this img tag anyway -->
<link rel="preload" href="/hero.avif" as="image">
<img src="/hero.avif" alt="">

<!-- keep: the URL exists only inside the stylesheet, discovered late -->
<link rel="preload" href="/hero-bg.avif" as="image">
<link rel="stylesheet" href="/app.css"><!-- .hero { background-image: url(/hero-bg.avif) } -->

go deeper

for a junior

Understand that a preload is a real download competing with everything else on the page, so adding one for every asset makes the important ones arrive later rather than sooner.

for a middle

Explain the mechanism: preload issues a mandatory early request at a priority set by as, requests multiplex over one connection and share its bandwidth, and the preload scanner has already found anything visible in the markup.

for a senior

Demonstrate a diagnosis path. Read the waterfall around the LCP resource, remove hints and compare repeated runs, and confirm the outcome in field data because a fast local connection hides the contention entirely.

for a principal

Set the policy that stops the accumulation. Define what qualifies as a preload-worthy resource, generate hints from the build where possible, and require each new one in review to justify both that the first screen needs it and that the browser would find it late.

## Preload reorders; it does not add capacity The belief behind fourteen preloads is that hints make things faster. They do not. A hint changes **when** the browser learns about a resource and **what priority** the request gets. The pipe is the same size it was, and on a mobile connection it is a small pipe. Over HTTP/2 and HTTP/3 all those requests are multiplexed over a single connection and share its bandwidth, so starting fourteen transfers early does not make fourteen things arrive early — it makes all of them, including the LCP image, arrive later than if the browser had been left to sequence them by its own priority model. That is the core mechanism, and it is why over-hinting shows up as a *regression* rather than a wash. ## The three ways the fourteen tags hurt **1. They compete with the critical path.** A preload declared `as="style"` or `as="font"` is treated as urgent. Fourteen urgent requests, issued before the parser has even reached the body, contend with the render-blocking stylesheet and the hero image. Bytes spent on a route chunk are bytes not spent on the pixels the LCP measurement is waiting for. **2. Most of them buy no discovery.** The browser's preload scanner reads ahead through the raw HTML and starts fetching `<img src>`, `<script src>` and `<link rel="stylesheet">` before the parser gets there. A preload for something already visible in the markup near the top of the document adds a request the browser was about to make anyway — pure contention, zero discovery. The hint only earns its place when the resource's URL is *not* in the HTML. **3. Some fetch things the page does not need.** Below-the-fold images, a modal's assets, another route's chunk. These are the most damaging, because the bandwidth is not merely reordered — it is spent on something that contributes nothing to the current view. A fourth, quieter cost: unused preloads. Any hint whose consumer never appears produces a console warning that the resource was preloaded but not used, and in the mismatch cases (missing `crossorigin`, wrong `as`, an image the layout resolves differently) the file is fetched twice. ## The keep/drop test A preload has to pass **both** halves of one question: > Does the current viewport need this resource, *and* would the browser otherwise find it late? - **Needed and found late — keep.** An LCP image referenced only by a CSS `background-image`. A font whose URL appears inside the stylesheet. A JSON payload the app requests after boot. In each case the resource sits behind at least one other download, and the hint removes a round trip from the critical chain. - **Needed but found early — drop.** An `<img>` at the top of the body. A stylesheet already linked in the head. The scanner has it. - **Found late but not needed yet — drop.** The route the user might click next; this is prefetch's job, at idle priority, not preload's. - **Neither — drop, obviously.** Fourteen tags almost never survive this. A page with a handful of genuinely late-discovered critical resources is normal; a page with fourteen of them usually has a structural problem worth fixing instead — the critical assets are buried too deep, or the first screen depends on far too much. ## How to verify rather than argue Reasoning about priorities is how teams end up with fourteen preloads in the first place. Measure: 1. **Read the waterfall for the LCP resource specifically.** When was it requested, when did it finish, and what else was in flight during that window? If the answer is "nine other things", you have found your contention. 2. **Remove and compare.** Strip the hints, re-measure under identical conditions, then add back only the candidates that pass the test above, one group at a time. Lab runs vary, so compare repeated runs rather than single numbers. 3. **Confirm in the field.** Local conditions flatter you: a fast connection hides bandwidth contention almost completely, which is exactly why over-preloading survives code review and then shows up in real-user LCP. The regression lives at the slow end of the distribution. 4. **Watch the console.** Unused-preload warnings and duplicated URLs in the waterfall are free evidence that specific tags are pure cost. ## Keeping it from coming back Hints are side effects with no compile-time consumer, so nothing breaks when they go stale — which means they accumulate. Generate them from the build manifest where you can, keep a short written rule for what qualifies, and treat every new preload in review as a claim that needs the same two-part justification: needed now, and otherwise discovered late.

  • How do you tell whether one specific preload is doing anything at all?
    Remove it and compare under identical conditions, repeated enough times to see past run-to-run noise. Before that, check the waterfall: if the resource started at roughly the same moment with and without the hint, the preload scanner had already found it and the tag is pure contention. Console warnings about unused preloads settle the easy cases immediately.
  • Which resources genuinely deserve a preload on a typical page?
    The short list is late-discovered and critical: an LCP image referenced from CSS rather than markup, a font used in the first paint whose URL lives in the stylesheet, and a data request the application issues immediately after boot. Each of these sits behind another download, so the hint removes a link from the critical request chain rather than just adding a competitor.
  • Why does this regression usually survive local testing?
    Because bandwidth contention barely exists on a fast wired connection — fourteen parallel transfers all finish quickly, so the lab number looks fine or even improves. The cost appears on slow mobile connections, which is where the field distribution's slow tail lives. Judge hint changes on real-user data, or at minimum on a throttled profile.

Preload is a fast-track lane at the airport. Give it to the two passengers whose flight boards first and they make it; hand it to everyone in the terminal and you have simply rebuilt the ordinary queue, having spent money on lanyards.

saying these in an interview costs you the question

  • Believes more preloads always means faster
  • Preloads resources already present in the markup
  • Preloads below-the-fold and next-route assets
  • Ignores that bandwidth is shared and finite
  • Validates hints only on a fast desktop connection

context