Skip to content
Core Web Vitals & measurement

Reading the network waterfall: what each row reveals

Learn to read the network waterfall: how it is ordered, what the phases of a bar show and which six patterns across rows reveal typical slowdowns.

20 min read Performance-AnalyseWasserfallLCPTTFB

In short and in plain language

A waterfall shows all the files a page loads. Each file is a row. The bar shows when it starts and how long it takes.

Read the waterfall as a picture. Patterns across many rows matter. A staircase means one file waits for another.

The biggest image at the top of the page should start early. If it starts late, there is a gap. Then visitors see the page later.

Some rows wait a long time for the server. Others come from other companies. Both can slow the page down.

We measure the page and look for the patterns. Then we fix the cause and measure again.

Many articles about load time end with the same advice: check the network waterfall. Anyone who then opens the tool sees dozens of colored bars and has no idea where to start. The median page makes 72 requests on mobile (Web Almanac 2025), and each of them is a row. Read one by one, hardly any of these rows tells you much. The waterfall only becomes revealing when you read it as a picture: where do the bars form a staircase, where does a gap open up before the most important image, where does a row wait conspicuously long, where does a block of third-party addresses gather? This article explains how the chart is ordered and what the segments of a bar mean. It then describes six patterns across multiple rows that reveal typical slowdowns, each with the first lever to pull and the in-depth article behind it. The browser's developer tools are all you need; the description follows the network reference published by Chrome for Developers.

Key takeaways

  • The waterfall orders requests by start time: whatever begins farther to the left started earlier (Chrome for Developers). Read the pattern formed by several rows; the phases of a single bar only serve as a legend.
  • When each request starts only after the previous one has finished, the waterfall forms a staircase of dependencies. Every step costs at least one round trip; the lever is a flatter chain, not a smaller file.
  • If the LCP image starts well after the first resource, there is a gap. Resource load delay should stay below 10 percent of LCP (web.dev); about 16 percent of pages lazy-load their LCP image (Web Almanac 2025).
  • If the Initiator column shows a script or stylesheet, the file was discovered late; a long Queueing segment points to a priority that is too low. What helps: src in the HTML and fetchpriority="high" on exactly one image.
  • A long Waiting (TTFB) segment contains server time plus one round trip (Chrome for Developers). For the document, a TTFB of up to 0.8 seconds counts as good (web.dev); Server-Timing shows where backend time goes.
  • Third-party rows start with their own connection setup and often hang together in chains. Before campaigns such as Black Week, compare the campaign page with the home page under identical test conditions.

How the waterfall is ordered

The network panel in the developer tools shows every request a page makes as a row in a table: name, status, type, initiator, size, time and, on the far right, the waterfall. This column is the only one that displays time as an area. The network reference from Chrome for Developers describes its purpose in three short sentences:

Use the Waterfall to view the timing of requests in relation to one another. By default, the Waterfall is organized by the start time of the requests. So, requests that are farther to the left started earlier than those that are farther to the right.

Chrome for Developers, Network features reference

Three reading aids follow from this. First, the vertical order is a temporal one: a row further down was initiated later, but it does not have to finish later. Second, the horizontal distance between the starts of two bars means the browser either learned about the second request later or was only allowed to send it later. Third, the sort order can be changed: right-clicking the table header offers response time, end time, total duration and latency in addition to start time (Chrome for Developers). For the pattern reading in this article the default remains the right choice, because almost all patterns are start-time patterns.

The panel draws two vertical lines itself: blue stands for the DOMContentLoaded event, red for the load event. More important for the question of speed is a third line that is missing there: the moment of the Largest Contentful Paint. It comes from the performance recording in the Performance area of the same tool. Anyone who adds it mentally to the waterfall, or draws it on a screenshot, splits the requests into two groups. Whatever lies to the left of the LCP line may have delayed LCP. Whatever lies to the right no longer affects it, though it still affects interaction, the main thread and data volume.

The sheer number already shows that the picture matters more than any single row. On desktop the median page even makes 77 requests (Web Almanac 2025). Hardly anyone checks that row by row. But anyone who knows what a staircase, a gap or a waiting bar looks like finds the two or three rows that matter within minutes, and can name them in the team so that everyone means the same spot.

Scope

How the time of a single request splits into DNS, connection, TLS and server response is covered in TTFB: Why Server Response Time Determines Everything. How LCP breaks down into its four phases is shown in Break Down LCP into Four Phases. This article is about what only becomes visible across multiple rows.

The phases of a bar as a legend

Every bar is divided into segments. Hovering over a bar shows a preview of the breakdown; it is permanently available in the Timing tab of each request. For pattern reading it is enough to recognize the segments. The table summarizes them based on the network reference (Chrome for Developers), using the labels the panel displays.

Segment in the panelWhat happensA long segment usually points to
QueueingThe browser holds the request back before the connection startsmore important requests first, connection limit under HTTP/1.1
StalledThe request stands still after the connection has startedthe same reasons as Queueing
DNS LookupThe name is resolved to an IP addressa new, previously unknown origin
Initial connectionConnection setup including TCP handshake and TLS negotiationa new origin without a prepared connection
Request sentThe request is being sentrarely conspicuous
Waiting (TTFB)Waiting for the first byte of the responseslow server, slow endpoint, distant origin
Content DownloadThe response body arriveslarge file, slow network, busy browser

Two details from the reference are particularly useful for reading. The Waiting (TTFB) segment contains one round trip of latency in addition to the server's processing time (Chrome for Developers). With a distant server it therefore becomes long even when the server itself responds quickly. And Queueing has a second cause besides priority: once six TCP connections are already open for an origin, the limit has been reached (Chrome for Developers). This only applies to HTTP/1.0 and HTTP/1.1; the Protocol column shows which protocol a request uses, with values such as h2 or h3.

From here on, the segments serve only as a legend. Pattern reading does not ask how long name resolution took for a particular request, but which rows hold each other up and where the browser is waiting for something it could have had earlier.

Preparation: a recording you can read

A waterfall is only as meaningful as the recording it comes from. Files from the browser cache, requests from extensions and a fast office network hide exactly the patterns you are looking for. Five settings make a recording readable and comparable with a later one:

  1. Disable the cache: The “Disable cache” checkbox emulates a first visit. Without it, files come from storage and staircases seem to disappear even though they still exist for new visitors.
  2. Throttle the network: The presets for fast 4G, slow 4G and 3G reveal waiting times that get lost in the office. If field metrics are enabled in the Performance area, the tool recommends a throttling option that matches data from real visits (Chrome for Developers).
  3. Exclude outside influences: Use a separate browser profile without extensions. Requests from extensions start with chrome-extension:// and can also be filtered out.
  4. Add columns: Right-click the table header to show the Priority, Protocol and Domain columns. With big request rows enabled, the Priority column shows both the initial and the final priority.
  5. Record from the start: The panel only logs what happens after it has been opened. So open the tool first, then reload, and enable “Preserve log” for redirects across several pages.

The “Capture screenshots” setting is also helpful. It takes screenshots while the page loads, and clicking a thumbnail filters out all requests that only started afterwards (Chrome for Developers). This shows at a glance, without any arithmetic, which requests ran before the first visible content and which only ran afterwards. For discussion within the team, the recording can be shared as a HAR file, specifically the sanitized version without cookies and credentials.

Measure the template that matters: product page, category, cart, campaign page. The home page is often not the slowest page of a shop, and its waterfall often differs markedly from that of a product page, because different images, scripts and endpoints are involved there. Every template therefore needs its own recording.

Pattern 1: the staircase of dependencies

Many people already know the staircase. Each row starts only where the previous one ends, and the bars descend diagonally toward the bottom right. Typical steps are the HTML, inside it a stylesheet, inside that an @import of a second stylesheet, and inside that a font. Or a loader script that fetches a bundle that requests data that finally names an image. Every step costs at least one round trip plus the server's response time, even if each individual file is small. On a throttled network, four small steps can add up to a waiting time longer than the download of all four files combined.

The Lighthouse documentation calls such chains critical request chains: series of dependent network requests that are important for page rendering. The longer the chains and the larger the downloads, the more significant the impact on page load (Chrome for Developers). Since Lighthouse 13, this audit lives in the “Network dependency tree” insight (Chrome for Developers). In the panel itself, a chain can be proven without any report: hold Shift and hover over a row, and the tool colors its initiator green and its dependencies red (Chrome for Developers).

The lever is to make the chain flatter, not to make every file smaller. Whatever the browser finds in the HTML it can request in parallel. A preload for the font, a link element instead of @import, critical CSS directly in the head of the page, or server-rendered HTML instead of content that a script generates first: each of these measures removes a step. What this looks like for styles is described in the article on Critical CSS.

A staircase without dependencies

A second form of staircase appears without any content dependency. Several fetches from the same page start at the same time, but their waiting segments end staggered, one after the other. That points to a lock on the server, such as a PHP session that processes parallel requests from the same session one after the other. How to recognize and resolve it is shown in The Session Lock.

Pattern 2: the gap before the LCP image

On 76 percent of mobile pages the LCP element is an image (Web Almanac 2025). In the waterfall you can therefore usually name the one row that matters: the file of the LCP image. The rule of thumb from web.dev is simple. The LCP image should start loading at the same time as the first resource the page loads (web.dev). If it starts much later, a gap opens up between the start of the first subresource and the start of the image, during which the connection sits idle for the most important file.

This gap is the resource load delay, the second of the four LCP phases. For a well-optimized page, web.dev gives this guideline: server response and resource loading each account for about 40 percent of LCP, resource load delay and element render delay each for less than 10 percent (web.dev). According to web.dev, the values are explicitly guidelines, not strict rules. In the waterfall a comparison is therefore enough: if the gap is wider than the image's download bar, this is where the biggest lever lies.

A common cause is quickly found. About 16 percent of pages lazy-load their LCP image and thereby delay the main content (Web Almanac 2025). In the waterfall, the image then only starts after layout, often behind several scripts. Other candidates are a hero area built as a carousel whose first image is inserted by a script, and a consent banner that itself becomes the largest element and pushes the actual image aside.

A second, usually narrower gap can sit after the image: between the end of its download and the LCP line. That is the element render delay. It occurs when the image has loaded but cannot be shown yet, for example because a stylesheet blocks rendering or because a script reveals the element only later. How to check the LCP image and the waterfall of a product page point by point is listed in the section LCP element and waterfall of the product page.

Pattern 3: late discovery via script or stylesheet

Not every gap has the same cause. The Initiator column shows what triggered a request: the HTML parser, a redirect, a script, an Early Hints response or some other process (Chrome for Developers). If the LCP image or a font lists a script or a stylesheet as initiator, the browser only found the file after it had loaded and evaluated that other file. In the waterfall this looks like a gap combined with a staircase: the image starts exactly where the triggering script ends.

The reason is the preload scanner. It reads ahead through the raw HTML while the main parser is still stuck on a stylesheet, and requests the files it finds in advance. What is not in the HTML as an address, it cannot see: a background image from the CSS, an image whose address a lazy-loading script hides in data-src, or an image that a script only adds to the page later. web.dev lists exactly these cases as examples in which the LCP resource cannot be discovered from the HTML (web.dev).

In the documentation's example, a rel=preload let the browser discover a background image around 250 milliseconds sooner than without the hint (web.dev); the test used a simple page on a simulated mobile connection. Yet only 2.1 to 2.2 percent of pages preload their LCP image (Web Almanac 2025). A preload is only necessary when the file is not already in the HTML, though; an img element with src or srcset in the delivered markup is usually better. Which hints help when, and when they waste bandwidth, is covered in the article on Resource Hints.

Pattern 4: the queue caused by priority

Sometimes a file is known early and still starts late. The bar then begins with a long Queueing or Stalled segment even though the connection seems free. The browser holds the request back because it considers others more important. Priority depends on the type of resource and its location within the document (Chrome for Developers). The Priority column shows how the browser decided and, with big request rows, whether the rating changed during loading. The priority: filter displays all requests of one level together.

Images are the typical case. In Chrome they start at low priority and are only boosted at layout time if they are in the viewport. Since Chrome 117, the first five large images receive medium priority, and two of them can load in parallel during the initial tight phase (web.dev). That helps, but it does not replace a hint in the markup: with fetchpriority="high" the LCP image starts at high priority right away. This attribute now appears on 17 percent of mobile pages with an LCP image (Web Almanac 2025). How to set it and why it only helps on one element is explained in the article on fetchpriority.

The protocol plays its part. Under HTTP/1.1, the limit of six connections per origin also applies; queues then appear in the waterfall like blocks stacked on top of each other, because every further request waits for a free connection. Under HTTP/2, the requests to one origin share a single connection, and the standard recommends allowing at least 100 concurrent streams (RFC 9113). There, the deciding factor is not the number of connections but the order in which the server responds.

There is a dedicated signal for that order. RFC 9218 describes an urgency on a scale from 0 to 7, where smaller values take precedence (RFC 9218); if the value is absent, 3 applies (RFC 9218). Whether server or CDN honor the browser's signals is visible in the waterfall: if the LCP image arrives after large scripts despite high priority, the cause lies not in the markup but in delivery. Old tricks such as spreading files across many subdomains tend to do harm under HTTP/2: each subdomain needs its own connection setup, and across separate connections the browser can no longer manage priorities together.

Pattern 5: a long wait for an endpoint

A bar whose largest part is the waiting segment tells a different story. Here the browser sent its request long ago and is waiting for the first byte. The network reference also describes the difference visually: the lighter portion of a bar is time spent waiting, the darker portion is time spent downloading bytes (Chrome for Developers). A bar that consists almost entirely of the light portion is a server problem, not a file size problem.

What matters is which row is waiting. If the HTML document itself waits, everything after it shifts to the right, because before the first byte the browser does not know about a single subrequest. As a rough guide, web.dev rates a TTFB of 0.8 seconds or less as good and more than 1.8 seconds as poor (web.dev). If, on the other hand, a single fetch further down waits, such as an endpoint for prices, stock levels or the cart, the assessment depends on whether it lies to the left of the LCP line and whether visible content depends on its response. The Fetch/XHR type filter collects such requests in one view.

A long waiting segment on the document has three common causes: redirects before the actual page, an uncached page build on the server, and slow external systems queried during the response. Redirects appear as separate rows above the document. What happens within the server time, however, is not shown in the waterfall unless the server sends a Server-Timing header; its entries appear in the request's Timing tab. How to set it up is described in Server-Timing. The server-side remedies, from page cache to database, are bundled in our TTFB optimization.

Pattern 6: the third-party block

The sixth pattern shows up in the Domain column: a group of rows from other origins, each starting with its own name resolution and its own connection setup. At least 90 percent of pages involve one or more third parties (Web Almanac 2025). These rows often hang together, because a tag manager loads a script that loads another one. The median depth of such inclusion chains is 3 (Web Almanac 2025). That is the staircase from the first pattern, only on servers whose response time you cannot influence.

Two questions matter for speed. First: does the block lie to the left of the LCP line and compete with the LCP image for bandwidth and the main thread? Second: does the LCP image itself come from another origin? On 16 to 18 percent of pages, the LCP image is hosted on a different host than the document (Web Almanac 2025). Its download is then preceded by a separate connection setup, which a preconnect can bring forward or which serving the image from your own domain avoids entirely.

Whether a third-party script really slows things down can be tested without removing it. The domain: filter shows only the rows of one origin, and the Invert checkbox hides them instead (Chrome for Developers). In the Request Conditions panel, individual addresses can be blocked on a trial basis, and comparing two recordings shows what the page gains without them. How to decide afterwards what stays, what loads later and what gets replaced by a facade is described in Trimming Third-Party Scripts.

From pattern to action

The six patterns can be checked in a fixed order. It starts at the LCP line, because that line divides requests into critical and non-critical ones, and ends with the third-party block, because its lever is usually a decision for the team rather than a change in the code. The table summarizes signs, causes and the first lever.

PatternHow to spot itCommon causeFirst lever
Staircaseeach row starts where the previous one ends@import, loader scripts, markup generated in the browserflatten the chain, announce files in the HTML
Gap before the LCP imageimage starts well after the first resourcelazy loading, carousel, image from a scriptimg with src, without loading="lazy"
Late discoveryinitiator is a script or stylesheetbackground image, data-src, rendering in the browsermove into the HTML or preload with high priority
Queuelong Queueing or Stalled segmentlow priority, limit under HTTP/1.1fetchpriority, HTTP/2 or HTTP/3
Long waitthe light waiting segment dominatesredirect, server time, external systemcache, Server-Timing, remove redirects
Third-party originown DNS and connection segments, Domain columntag manager, pixels, widgetsremove, defer, preconnect for essential services
  1. Identify the LCP element in the Performance area and find its file in the waterfall.
  2. Check the document row: how long is the waiting segment, are there redirects in front of it?
  3. Compare the start of the LCP image with the start of the first resource: is there a gap?
  4. Read the Initiator and Priority of the LCP image: discovered late or rated too low?
  5. Look for staircases to the left of the LCP line and trace the chain while holding Shift.
  6. Use the Domain filter to determine the share of third-party rows to the left of the LCP line.

Every change is followed by a second recording with the same settings. A waterfall proves an improvement less in milliseconds than in the picture: the staircase has one step fewer, the gap is closed, the LCP image sits higher up. Whether real visitors notice is answered by field data. Anyone who needs this analysis for a whole family of templates will find it in our technical analysis; implementation in the theme is part of front-end optimization.

Before Black Week: walk through campaign pages once

At the end of November, the home page of many shops changes, and with it the waterfall. Campaign banners, countdown scripts, additional campaign pixels and new landing pages are added, often at short notice and without a measurement of their own. Each of these additions can create one of the six patterns: the banner becomes the new LCP element and starts via script, the pixel opens a new third-party block, the landing page hangs on a redirect from the campaign URL.

The effort for this check is manageable. One recording of the campaign page and one of the regular home page, both with the cache disabled and the same throttling, placed side by side, immediately show what is new. Together with warming the cache for the sale launch, that is a well-spent hour before a week with heavy campaign traffic. These points belong on the list:

  • The LCP element of the campaign page is known, sits in the HTML as an img with src and carries no loading="lazy".
  • The campaign banner is not inserted by a script and starts in the waterfall next to the first resource.
  • New pixels and countdown scripts sit to the right of the LCP line or only load after the first interaction.
  • Campaign URLs lead directly to the target page without a chain of redirects.
  • The document's waiting segment is no longer on the campaign page than on the home page.
  • Images on the campaign page carry suitable srcset and sizes values so that mobile devices do not load a file in desktop width.

Sources and documentation

This article is based on data from: Chrome for Developers (Network features reference; Lighthouse: Avoid chaining critical requests); web.dev (Optimize Largest Contentful Paint; Don't fight the browser preload scanner; Optimize resource loading with the Fetch Priority API; Time to First Byte); HTTP Archive Web Almanac 2025 (chapters Performance, Page Weight and Third Parties); RFC 9113 (HTTP/2); RFC 9218 (Extensible Prioritization Scheme for HTTP).

Related Articles

Server & hosting

WordPress Slow Despite Caching: WP-Cron and admin-ajax

Page cache on, WordPress still sluggish? WP-Cron, Heartbeat and admin-ajax bypass the cache and tie up PHP workers. How to measure that load and take it off.

19 min read
Front-end optimisation

Less JavaScript: Dialogs and Popovers Straight in HTML

Dialogs, menus and filter drawers without custom scripts: how command and commandfor work, which fallback older browsers need and what it all means for INP.

17 min read
Shops & CMS

Pagination, Load More or Infinite Scroll: Fast Listings

Pagination, load more or infinite scroll in shop listings: how initial load, INP, layout shifts, returning to the same spot and a URL per page fit together.

21 min read