What is each row in a waterfall?
Each row is one request: the page itself, a stylesheet, a script, an image, a font. Rows are listed in the order the browser asked for them, and a shared timeline runs across the top, so a bar's left edge shows when the request began and its right edge shows when the last byte arrived.
The shape of the whole chart tells a story before you read any detail. A tall, narrow stack near the left means the browser found most files early and fetched them together. A staircase, where each bar starts as the one above it ends, means the files were found one after another. Long bars far to the right are the late arrivals, and the important question is whether anything on screen was waiting for them.
On the starting bakery page there are five rows: the HTML, site.css, stars.js from reviews.example.net, and two photos. The page is about 335 KB in total, but the first paint waits until about 2.1 seconds, and the timeline shows exactly which bars it waited for.
What do the parts of a bar mean?
A bar has up to three parts. The first is connecting: looking up the server, opening a connection and setting up encryption. On this pretend 4G network that takes three round trips of 150 milliseconds, so 450 milliseconds, and it happens once per site. The second is waiting: the request has been sent and the server is working out the answer. The third is downloading: bytes are arriving, and this part grows with the file size.
Reading the parts tells you what kind of problem you have. A long download means too many bytes; make the file smaller. A long wait means the server is slow; that is a server fix, often caching or a lighter page build. A long connection means the file comes from a site the browser hasn't talked to yet; you can remove that site, host the file yourself, or warm the connection early with a hint.
The stars.js row on the starting page has all three: about 450 milliseconds connecting to a new site, about 230 milliseconds of waiting while the request travels and the other server thinks, and then a download that shares the network with everything else. Your own files skip the connecting part, because they reuse the connection the HTML already opened.
stars.js [connect 450 ms][wait 230 ms][download ......]
site.css [w][download]
loaves.jpg [w][download ..................]

What are the first paint and largest paint markers?
Two vertical lines cross the chart. First paint marks the moment anything at all appeared on screen. Largest paint marks when the biggest text block or image in the first screen appeared, the moment the Vitals view calls Largest Contentful Paint (LCP).
Those lines turn the chart from a list of downloads into an answer. Any bar that ends just before the first paint line and is tagged “blocks paint” or “blocks parser” is holding the whole screen back. Any bar that ends at the largest paint line is the main content itself, and the bars running alongside it are competing with it for the network.
On the starting page, first paint sits just after stars.js has finished and run. Largest paint sits at the end of the loaves.jpg bar. Those are the two rows worth fixing; nothing else on the page is in the way.
Why does a script from another site cost so much?
A file from another site needs its own connection, and on a phone that is the slowest part of many requests. The reviews script is only 70 KB, yet its row starts with almost half a second of connecting before a single byte arrives. Because it is a plain <script src> in the head, the parser stops there, and the screen stays blank the whole time.
The script fills a box near the bottom of the page with star ratings. Nothing at the top depends on it. Adding async lets the browser keep reading and painting while the script downloads, and run it whenever it arrives. In the solution the first paint moves from about 2.1 seconds to about 1.1 seconds, and the reviews still appear.
Use async for independent scripts that don't care about order, such as most widgets. Use defer for your own scripts that depend on each other or on the full page being parsed. A later lesson covers third-party scripts in more depth, including ones that are better removed.
<script src="https://reviews.example.net/stars.js" async></script>What does priority change?
All downloads share one network link. When several files are downloading at once, the browser splits the link between them by priority. In this simulator a high priority file gets four shares for every one share a low priority file gets. Stylesheets in the head get the highest priority; images start low, because the browser can't yet tell which ones are on screen.
On the starting page the two photos start together and share the link equally, so the loaves photo at the top finishes at about 2.6 seconds, only a moment before the ovens photo further down. Neither file is too big. The top photo was waiting its turn.
Adding fetchpriority="high" to the top photo tells the browser this is the image people see first. In the solution it finishes at about 1.9 seconds while the ovens photo still arrives a little later. The page downloads exactly the same 335 KB; it just downloads them in a better order.
<img src="/img/loaves.jpg" alt="Sourdough loaves on the counter"
width="800" height="533" fetchpriority="high">Which tags should you look for?
The simulator tags rows with what they did to the page. “Blocks paint” is a stylesheet the first paint must wait for. “Blocks parser” is a script that stopped the HTML being read. “Lazy” is an image or frame that waited until it was near the screen. “From cache” appears on the second visit for files the phone kept. A red row with 404 is a file the page asked for that the server doesn't have.
A short checklist covers most pages: any blocking tag on a file that doesn't need it, any late start on something in the first screen, any long connection to another site, and any 404. Fixing those four usually moves the numbers more than shaving kilobytes.
How do you read a waterfall in Chrome DevTools?
Open DevTools with F12, choose the Network panel and reload the page. The Waterfall column draws the same bars, and hovering one shows its timing broken into the same parts: queueing, connection setup, waiting for the server (labelled time to first byte) and content download. The Priority column can be switched on by right-clicking the column headers.
Turn on throttling in the toolbar to see a phone's view; on fast office broadband everything looks instant and the problems hide. The Initiator column shows what caused each request, which is how you find a file pulled in by a script or a stylesheet. The Performance panel shows the same requests next to the paints and the main thread.
Where does the simulator differ from a real waterfall?
Real waterfalls are messier. Browsers queue requests, reuse connections in more complicated ways, and real servers vary from one request to the next. HTTP/2 and HTTP/3 also share a connection between files differently from this simulator's simple shares. Expect real bars to wobble and to start a few milliseconds apart for reasons that have nothing to do with your page.
The habits still transfer: find what the first paint waited for, find what the largest paint waited for, and question every long connection and every late start.
What does AI advice often miss when reading a waterfall?
Asked to speed up a page, AI tools tend to look at total size and suggest compressing or minifying everything. On this page that would barely help: the slow parts were one connection to another site and one photo waiting its turn. Neither shows up in a size total; both are obvious in the waterfall.
AI-written pages also often add fetchpriority="high" to every image, or preload to every file. Priority is a share of a fixed link, so if everything is high, nothing is. Pick the one or two files the first screen depends on.
Field notes
- Each row in a waterfall is one request, placed on a shared timeline.
- A bar shows connecting, waiting for the server and downloading.
- A script from another site needs its own connection, which takes time.
- Files share one network link, and higher priority gets a bigger share.
Easy to get wrong
Priority decides how the network is shared. Marking every image high puts them back on equal terms, and the important one waits again.
A small file can hold up the whole screen if it blocks, and a large one may not matter at all if it is far down the page.
A widget from another site pays for a new connection before downloading. Without async the whole page waits for that connection, the download and the script's run.
Questions people ask
Why are some bars all download and no connection?
Files from the same site reuse the connection the HTML opened, so they skip the connecting part. Only the first request to each site pays for it.
Does fetchpriority make the file smaller?
No. It changes only how the network is shared while files download together. The same number of bytes arrive; the important ones arrive first.
Is a waterfall the same as a Lighthouse report?
Lighthouse runs the page and gives scores and suggestions based on what happened. The waterfall is the raw record of requests underneath. When a Lighthouse suggestion is unclear, the waterfall usually shows what it means.
What does a 404 cost if nothing is shown?
It still costs a request, a wait for the server and sometimes a new connection, and the broken image or missing style may change the page. Clearing 404s is a quick win.