Fix "Avoid Chaining Critical Requests" in Lighthouse

Arjen Karel Core Web Vitals Consultant
Arjen Karel
linkedin

"Avoid Chaining Critical Requests" in short

Critical requests are network requests that the browser fetches with high priority.

When a page or a script causes multiple resources to be downloaded with high priority, one after another, we call that a chain of critical requests.

A browser will not (fully) start rendering and painting the page until all of these critical resources have been downloaded. Any critical resource can therefore block the first rendering of a page. The larger the critical request chain becomes, the more it delays the First Contentful Paint and Largest Contentful Paint.

Last reviewed by Arjen Karel on March 2026

Critical request chain example

How the download priority is determined

Critical requests are the resources that are downloaded with high priority during initial page load. How is this priority determined?

The download priority is determined by the browser itself. The browser follows a set of rules to determine the priority of each asset. Which elements ultimately receive the highest priority depends on the structure of the page. The elements that your browser thinks are necessary for the first rendering of the page are given the highest priority.

Your browser initially makes an educated guess at which elements are most important. Generally speaking, the download priority works like this: HTML always takes the highest priority, then stylesheets, synchronous JavaScript, fonts, AJAX requests, images at the top of the page, images later on the page, and then asynchronous JavaScript.

You can override these priorities with the fetchpriority attribute. Setting fetchpriority="high" tells the browser a resource is more important than it would normally guess. Setting fetchpriority="low" does the opposite. This attribute now has 93% browser support. For a complete guide, see Resource Prioritization and the Core Web Vitals.

You can see which resources are given high priority on your page. Open DevTools with Ctrl+Shift+J. Navigate to the Network tab, right-click on the column names and select 'Priority'.

Dev Console Resouce Priority

How does the critical request chain affect page load time?

When loading a page, a browser starts in "display blocking" mode. In this mode, the most important resources are downloaded with high priority. Those are the critical resources.

A browser will not (fully) start rendering the page until all critical resources have been downloaded. So any critical resource can block the first rendering of a page.

The fewer critical resources a page has, the less work the browser has to do to get the first content on the screen, and the less competition there is for the CPU and other resources.

According to the 2025 Web Almanac, only 15% of mobile pages pass the render-blocking resources audit. That means 85% of the web still has critical chain problems to solve. This is one of the main reasons why only 55% of mobile origins score "good" on First Contentful Paint. Across sites monitored by CoreDash, origins with fewer than 3 critical chain requests have a median FCP of 1.2 seconds, compared to 2.4 seconds for origins with 8 or more chain requests.

Note: As of Lighthouse 13 (October 2025), this audit has been renamed to the "Network Dependency Tree" insight. The concept is the same: Lighthouse analyzes the chain of high-priority network requests and flags when it is too deep.

How to fix "Avoid Chaining Critical Requests" in Lighthouse

You can reduce the impact of critical requests in three ways:

  1. Reduce the number of critical resources. Convert critical resources to non-critical resources by removing or deferring them.
  2. Reduce the number of critical bytes. Reducing the size of critical path resources makes them download faster. Gzip or Brotli compression, JavaScript tree shaking, image optimization, and font subsetting all help.
  3. Improve the download order of the critical path. Use resource hints such as preloading to skip resource discovery and ensure that the critical resources are downloaded as quickly as possible. Use HTTP 103 Early Hints to start preloading resources before the HTML even arrives.

Which option is best depends on the file type of the resource:

1. HTML

The HTML itself is always downloaded with the highest priority. The page is always part of the critical request chain. That is why the page itself is the first thing to consider when optimizing.

Delayed loading of content: Many large sites, such as Google itself, use this technique to reduce the critical request chain. On the search results page, for example, parts of the content that are not immediately needed are only loaded later via an AJAX request.

Minify: Smaller is always faster. Use HTML minification to remove comments, spaces, and blank lines from the page.

Compression: Compress your HTML with Brotli or Gzip. Brotli typically achieves 15 to 20% better compression than Gzip.

2. Stylesheets

Stylesheets in the head of the page are always critical. Without styles, a browser does not know what the page will look like. Stylesheets are therefore a standard part of the critical request chain.

Critical CSS: The most effective way to break the CSS chain is to inline your critical CSS directly in a <style> tag in the <head>. This eliminates the render-blocking network request entirely. You can generate critical CSS through NodeJS tools or through the Critical CSS Generator. Place critical CSS inline and load the rest at a lower priority:

<link rel="preload"
      href="css.css"
      type="text/css"
      as="style"
      onload="this.onload=null;this.rel='stylesheet';"/>

Watch as something strange now happens on the page. First the page is shown without styles, and only after loading the CSS the styling is applied. All content will flash from unstyled to styled. That is why you need critical CSS: the CSS rules for the visible part of the page are inlined, so the page looks correct immediately, and the rest of the CSS loads without blocking rendering.

Avoid CSS @import chains: If your CSS files use @import to load other CSS files, you create a chain where the browser must download file A before it even discovers it needs file B. Replace @import statements with separate <link> tags or concatenate the files at build time. This is one of the most common causes of unnecessarily deep critical chains.

Media queries: Load only the styles your device needs. If a visitor is on mobile, they do not need to download the desktop or print styles. Use the media attribute to make stylesheets non-blocking for devices that do not match:

<link href="all.css" rel="stylesheet" media="all">
<link href="print.css" rel="stylesheet" media="print">
<link href="desktop.css" rel="stylesheet" media="screen and (min-device-width: 1024px)">

The browser only downloads stylesheets whose media attribute matches the current device at high priority. Non-matching stylesheets are downloaded at a low priority and do not block rendering.

Minify: Remove unused CSS. Many sites use CSS libraries such as Bootstrap. These libraries are often over-complete and not all style declarations are used. Edit these libraries via a CSS preprocessor (such as Sass) to remove unused style groups. Preprocessors also minify your CSS by removing all spaces and newlines. See also how to fix 'remove unused CSS'.

Compression: Compress stylesheets with Brotli or Gzip compression.

3. JavaScript

JavaScript files in the head of the page are downloaded with high priority by default and block the rendering of the page while they are being downloaded and executed. JavaScript is therefore a standard part of the critical request chain.

Defer and Async: Adjust the priority of JavaScript files by loading them asynchronously through the async or defer attribute. Async scripts are downloaded in parallel with lower priority. Deferred scripts are also downloaded in parallel and their execution is delayed until after the HTML has been parsed. For a complete comparison, see async vs defer and how they affect the Core Web Vitals.

// blocks loading and execution
<script src="normalscript.js"></script>
// async does not block during load, but it does block during execution
<script async src="asyncscript.js"></script>
// defer does not block during loading or execution
<script defer src="deferscript.js"></script>

For more techniques to defer JavaScript, see 16 methods to defer or schedule JavaScript. If you have unused JavaScript that cannot be deferred, see how to reduce unused JavaScript.

Code splitting and preloading: If the page does not allow JavaScript to load asynchronously, split JavaScript into multiple files. Place the part that is critical during page load in a small file and preload it. Place the non-critical JavaScript in another file and let it load deferred or async.

Minify: Shrink the number of bytes through a JavaScript minifier. Modern bundlers like webpack, Rollup, and Vite use terser under the hood to analyze JavaScript and make it as small as possible.

Compression: Reduce the number of bytes by compressing JavaScript via Gzip or Brotli.

4. Web fonts

Web fonts are usually the last files in the critical request chain. This is because web fonts rely on discovery: they are only loaded when a browser finds out that they are needed. For this, a browser must first analyze the HTML and look up in the stylesheet which font is used.

Preloading: When you know that you are going to use a font, it is faster to preload this font. The font is then downloaded as early as possible, minimizing the influence on the critical request chain. Preload a font by adding this code as early as possible in the head of the page:

<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>

Font strategy: There are many other ways to make fonts load faster. See how to self-host Google Fonts and how to ensure text remains visible during webfont load.

  • Always use self-hosted web fonts, never remotely hosted fonts like Google Fonts.
  • Resize the font with font subsetting.
  • Load non-critical fonts through the FontFace API.
  • Use font-display: swap to avoid fonts from blocking the initial rendering.
  • Let browsers generate their own font variants through font synthesis.

5. Images

Images that appear in the visible viewport during page load can also be given high priority and can interfere with the critical path. When you are sure that an image will always appear in the visible part of the website, preload this image. Add fetchpriority="high" to tell the browser it is the most important image on the page:

<link rel="preload" as="image" href="important-image.webp">

For all images that are not immediately visible, lazy load these images. Use loading="lazy" to delay loading the image until just before it becomes visible:

<img loading="lazy" src="lazy-image.webp" width="20" height="20" alt="...">

6. AJAX requests

AJAX requests are always assigned a high priority. Therefore, postpone AJAX requests until the page has finished rendering. Wait until the page has sent the "load" event:

window.addEventListener('load', (event)=>{
  console.log('this is a good time for an AJAX request');
});

If it is not possible to postpone the AJAX request, you can preload the resource to make it available to the browser sooner.

7. Iframes

Iframes are usually downloaded at high priority. Because an iframe is actually a page within a page, an iframe can cause a significant delay in page loading times. The resources that the iframe requires may also be downloaded at high priority and form their own critical request chain. The use of iframes can therefore significantly affect your Core Web Vitals.

You can delay loading an iframe via the loading="lazy" attribute. That often makes a big difference when the iframe is not immediately visible during loading. For more control over timing, inject the iframe through JavaScript to make sure it does not end up in the critical request chain. See how to embed Google Maps without hurting your PageSpeed and how to embed YouTube with perfect Core Web Vitals for examples of this technique.

Verify your improvements

After optimizing your critical chain, verify the improvement with Real User Monitoring. Your FCP and LCP should both improve. Lab tools like Lighthouse give you instant feedback, but field data from real users is what counts for the Core Web Vitals.

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

Your Lighthouse score is not the full picture.

Lab tests run on fast hardware with a stable connection. I analyze what your actual visitors experience on real devices and real networks.

Analyze Field Data
Fix 'Avoid Chaining Critical Requests' in LighthouseCore Web Vitals Fix 'Avoid Chaining Critical Requests' in Lighthouse