Latency vs bandwidth
Round trips, not megabits, decide how fast most pages load. See it in real Chrome recordings, measure your own round trip, and learn to count them.
- 01Tell latency from bandwidthSay what bandwidth, latency and round-trip time each measure. Explain why the speed of light sets a floor under every round trip.
- 02Explain why round trips usually winSplit a load into waiting and downloading. Use real recordings to show why more bandwidth stops helping, while every millisecond of round trip counts again and again.
- 03Count a page's round tripsAdd up the round trips a page waits for, from setting up a connection to a phone's radio waking up, and turn them into time.
Two ways a connection can be slow
Ravi pays for a faster internet plan. His old plan carried 20 megabits every second. A megabit is a million bits, the 0s and 1s that all data is made of. The new plan carries 100 megabits, five times as much. That evening he opens the tea of the week page at Leaf and Kettle, the tea shop from the first lessons. He expects the tea's picture to pop up five times sooner. It doesn't. It shows up at almost the same moment as before.
What did the faster plan buy him? The course loaded the same page in Chrome 156 on both connections, and wrote down when the picture appeared:
// The tea of the week page, loaded twice in Chrome.// Both times, a message took 150 ms to reach the server and come back.const on20Mbps = { lcpMs: 704 };const on100Mbps = { lcpMs: 676 }; console.log(`On 20 Mbps, the tea's picture appeared at ${on20Mbps.lcpMs} ms.`);console.log(`On 100 Mbps, it appeared at ${on100Mbps.lcpMs} ms.`);console.log(`Five times the bandwidth saved ${on20Mbps.lcpMs - on100Mbps.lcpMs} ms.`);- Lines 1 and 2 are comments. They say what was measured: the same page, twice, with every message taking 150 ms to reach the server and come back.
- Lines 3 and 4 hold the two recorded times. LCP, Largest Contentful Paint, is the moment the biggest thing on the screen appears. On this page, that's the tea's picture. It's counted in milliseconds (ms) from the start of the visit.
- Lines 6 and 7 print them:
On 20 Mbps, the tea's picture appeared at 704 ms.andOn 100 Mbps, it appeared at 676 ms. - Line 8 subtracts one from the other. It prints
Five times the bandwidth saved 28 ms.
A saving of 28 ms is far too small for anyone to notice. So where did the rest of the 676 ms go? Here is the 20 Mbps load, one bar per request. Each bar starts when the browser asks for a file, and ends when the file has arrived:
The page made four requests, one after another:
- the page itself, the HTML;
app.js, the script the HTML names;teas.json, the list of teas the script asks for;- the tea's picture, whose name is written in
teas.json.
Each request had to wait for the one before. The browser can't ask for the picture until it knows the picture's name. It only learns that name from teas.json.
Now look at how long the bars are. The files are small. Three of them are under 1 KB, a kilobyte, which is a thousand bytes. The picture is about 100 KB. At 20 Mbps, even the picture downloads in about 40 ms. So most of each bar isn't downloading. It's waiting: the request travelling to the server, and the reply travelling back.
A message there and its reply back is called a round trip. This page needs four of them in a row. At 150 ms each, that's 600 ms of waiting, on any plan.
That's the answer to Ravi's puzzle. A connection has two different speeds, and his plan only sold him one of them:
- Bandwidth is how much data the line can carry each second. It's counted in megabits per second, or Mbps. Bandwidth is the number on the plan.
- Latency is how long one message takes to get from one end to the other. It's counted in milliseconds.
- The round-trip time, or RTT, is how long a request takes to reach the server, plus its reply to come back.
Think of the road between your home and a shop. More lanes let more cars travel at once. But they don't make the drive any shorter. Now say you must drive to the shop and back four times, once for each item, one after another. A wider road barely helps you. A shop closer to home would.
- In real life: The number of lanes
- In JavaScript: Bandwidth: how much can travel at once
- In real life: How long the drive takes
- In JavaScript: Latency: how long one message takes to arrive
- In real life: The drive to the shop and home again
- In JavaScript: One round trip
- In real life: Four drives, one after another
- In JavaScript: Four requests in a row, like the tea page's
Here are the three words side by side. Read each row across, and compare the last column with the road:
| Word | What it means | Counted in | On the road to the shop |
|---|---|---|---|
| Bandwidth | How much data the line can carry each second. | Megabits per second (Mbps). | The number of lanes: how many cars can drive at once. |
| Latency | How long one message takes to get from one end to the other. | Milliseconds (ms). | How long the drive to the shop takes. |
| Round-trip time (RTT) | How long a request takes to get there, plus its reply to come back. | Milliseconds (ms). | The drive to the shop and home again. |
Bandwidth is how much can flow at once. Latency is how long one message takes to arrive, and the round-trip time is there and back. Most pages wait for several small requests in a row, and each one costs a round trip. So the number of round trips, times the round-trip time, usually decides how fast a page loads. More megabits only shrink the part spent downloading.
Round-trip time and the speed of light
Ravi's round trip took 150 ms. His messages were tiny, so why did each one take that long? And could a better connection bring it down to 1 ms?
Start with what one round trip is. The request travels to the server, the server answers, and the reply travels back:
On the way, a message doesn't travel in one piece. Data crosses the internet in small pieces called packets. Each packet passes through many routers. A router is a computer that reads a packet's address and sends it on toward the server.
Ilya Grigorik's book High Performance Browser Networking splits the time a packet takes into four parts. They're easiest to picture as a parcel going through the post:
You post a parcel to a friend in another city. Someone loads it onto a van, and the van drives the whole way. At each sorting office, someone reads the label to choose the next van. If an office is busy, your parcel waits in a pile until someone gets to it.
- In real life: The van driving from town to town
- In JavaScript: Propagation: the signal crossing the distance
- In real life: Loading the parcel onto the van
- In JavaScript: Transmission: putting the packet's bits onto the wire
- In real life: Reading the label at each sorting office
- In JavaScript: Processing: a router reading the packet's address
- In real life: Waiting in the pile at a busy office
- In JavaScript: Queuing: a packet waiting behind other packets
In network words, the four parts are:
- Propagation: the time the signal takes to cross the distance.
- Transmission: the time it takes to put the packet's bits onto the wire. A faster link does it sooner.
- Processing: the time each router takes to read the packet's address and choose where to send it next.
- Queuing: the time a packet waits at a busy router, behind other packets.
Better equipment can shrink the last three. Propagation is different. It depends only on the distance and on how fast the signal travels. And nothing travels faster than light.
Light covers about 300,000 km a second in empty space. Long-distance internet cables are made of glass fiber, and light is slower in glass: about 200,000 km a second. That's 200 km every millisecond. So how fast could a message cross the Atlantic and come back?
// Light in glass fiber covers about 200 km every millisecond.const fiberKmPerMs = 200;const route = { from: "New York", to: "London", km: 5585 }; const roundTripMs = (2 * route.km) / fiberKmPerMs;console.log(`${route.from} to ${route.to} and back: at least ${Math.round(roundTripMs)} ms`);- Line 2 is the speed of light in fiber: 200 km every millisecond.
- Line 3 is the route: New York to London, 5,585 km.
- Line 5 doubles the distance, because a round trip goes there and back. Then it divides by the speed: 11,170 km at 200 km every millisecond.
- Line 6 rounds the result and prints
New York to London and back: at least 56 ms.
It says "at least" because this is light in a perfectly straight cable, with no routers on the way. Grigorik's book does the same sum for three routes. Each row is one route, how far it is, and how fast light in fiber could cover it:
| Route | How far is it? | One way, in fiber | There and back, in fiber |
|---|---|---|---|
| New York to San Francisco | 4,148 km | 21 ms | 42 ms |
| New York to London | 5,585 km | 28 ms | 56 ms |
| New York to Sydney | 15,993 km | 80 ms | 160 ms |
Real messages are slower than the table. Cables don't run in a straight line between cities. And every router on the way adds processing and queuing. Grigorik puts the real round trip from New York to Sydney at 200 to 300 ms.
Often the slowest part isn't the ocean at all. It's the last few miles: the link from a home or a phone to its provider's network. Those first few hops alone can take tens of milliseconds.
Why does this matter? No amount of bandwidth shortens a round trip. Only a shorter distance does. That's why sites use a CDN, a content delivery network: copies of the site's files on servers all over the world. It works like a tea shop with a branch in every town, so nobody has to travel far. CDNs and the edge covers them later in the course.
How long is your own round trip to this site? Press Measure to find out. The panel asks for a tiny file ten times, and times each reply:
for (let i = 0; i < 10; i++) { await fetch(`${url}?n=${i}`, { cache: "no-store" });} const times = performance.getEntriesByType("resource") .filter((entry) => entry.name.includes(url)) .map((entry) => entry.responseStart - entry.requestStart); const roundTrip = Math.min(...times);const estimate = navigator.connection?.rtt;Nothing measured yet.
Press Measure. The panel sends 10 tiny requests to this site, one after another, and times how long each reply takes to start coming back.
The panel uses Resource Timing. For every file a page fetches, the browser writes down when it sent the request and when the first byte of the reply arrived. It's like a stopwatch the browser clicks twice for each file. In the panel's code:
- Line 7 subtracts those two times for each request: from sending it (
requestStart) to the first byte of the reply (responseStart). - Line 9 keeps the fastest one. Each time includes the server's own work and any queuing on the way. The fastest request had the least of both, so it's the closest to the pure round trip.
- Line 10 reads the browser's own guess,
navigator.connection.rtt. Chrome and Edge give it. Firefox and Safari don't.
Why more bandwidth stops helping
Back to Ravi. His plan got five times faster, and his page got 28 ms faster. Why does more bandwidth stop helping? A kitchen makes it easy to see:
You're making four pots of tea, one after another, and the only tap is at the end of the garden. For each pot, you walk to the tap, fill the kettle, and walk back. A stronger tap fills the kettle faster. But once filling takes a few seconds, a stronger tap saves almost nothing, because the walks take most of the time. A tap in the kitchen would save far more.
- In real life: How fast the tap pours
- In JavaScript: Bandwidth
- In real life: Filling the kettle
- In JavaScript: Downloading a file's bytes
- In real life: The walk to the tap and back
- In JavaScript: One round trip
- In real life: Four walks for four pots
- In JavaScript: Four requests in a row
- In real life: A tap in the kitchen
- In JavaScript: A server closer to the user
A page load works the same way. It has two parts: waiting for replies, and downloading the bytes. Here is one load as a simple sum, with round numbers:
// One load of a page, as a simple sum.// The page: 4 requests in a row, and 100 KB to download.// The line: 150 ms there and back, and 5 megabits per second.const waitingMs = 4 * 150;const downloadMs = (100 * 8) / 5; console.log(`Waiting for replies: ${waitingMs} ms`);console.log(`Downloading the bytes: ${downloadMs} ms`);- Lines 1 to 3 describe the page and the line. The page needs 4 requests in a row and 100 KB of files. The line has a 150 ms round trip and carries 5 Mbps.
- Line 4 is the waiting: 4 round trips of 150 ms each.
- Line 5 is the downloading. A byte is 8 bits, so 100 KB is 800 kilobits. A line of 5 megabits per second carries 5 kilobits every millisecond. So 800 kilobits take 800 ÷ 5 = 160 ms.
- Lines 7 and 8 print
Waiting for replies: 600 msandDownloading the bytes: 160 ms.
Now try two upgrades, one at a time. Which one helps more?
// The same sum, with one upgrade at a time.const waitingMs = 600; // 4 round trips of 150 msconst downloadMs = 160; // 100 KB at 5 Mbps console.log(`As it is: ${waitingMs + downloadMs} ms`);console.log(`Double the bandwidth: ${waitingMs + downloadMs / 2} ms`);console.log(`Halve the round trip: ${waitingMs / 2 + downloadMs} ms`);- Lines 2 and 3 are the two parts from the last example: 600 ms of waiting, and 160 ms of downloading.
- Line 5 adds them up. It prints
As it is: 760 ms. - Line 6 doubles the bandwidth, which halves only the downloading. It prints
Double the bandwidth: 680 ms. - Line 7 halves the round trip, which halves only the waiting. It prints
Halve the round trip: 460 ms.
Doubling the bandwidth saved 80 ms. Halving the round trip saved 300 ms. Bandwidth can only shrink the downloading part. The round trip shrinks the waiting part, and this page waits four times. It's the kettle again: a stronger tap only speeds up the filling, never the walks.
That's a sum on paper. Does a real browser agree? The course loaded the tea page in Chrome 156 under seven different networks. For each load, the recorder:
- added exactly one round trip to every request;
- capped the download speed at the bandwidth in the table;
- left the computer's processor at full speed, so only the network changed.
Each row below is one load. Read it across: the round trip, the bandwidth, when the picture appeared (LCP), and how long four round trips take on that network:
| Round trip | Bandwidth | When the picture appeared | Four round trips |
|---|---|---|---|
| 150 ms | 1.6 Mbps | 1,200 ms | 600 ms |
| 150 ms | 5 Mbps | 836 ms | 600 ms |
| 150 ms | 20 Mbps | 704 ms | 600 ms |
| 150 ms | 100 Mbps | 676 ms | 600 ms |
| 100 ms | 20 Mbps | 508 ms | 400 ms |
| 50 ms | 20 Mbps | 304 ms | 200 ms |
| 20 ms | 20 Mbps | 172 ms | 80 ms |
Here are the same seven loads as bars. On the left, only the bandwidth changes. On the right, only the round trip changes:
Three things stand out:
- Each step up in bandwidth helped less than the one before. Going from 1.6 to 5 Mbps saved 364 ms. Going from 5 to 20 Mbps saved 132 ms. Going from 20 to 100 Mbps, five times the bandwidth, saved just 28 ms.
- At 100 Mbps, almost all the time was waiting. The four round trips took 600 ms of the 676 ms before the picture appeared. That's 89%, and bandwidth can't touch it.
- Every cut to the round trip kept helping. From 150 ms down to 20 ms, the picture went from 704 ms to 172 ms. Each millisecond cut saved about 4 ms, once for each request in the chain.
Bandwidth does matter while the bytes are the slow part. At 1.6 Mbps, the 100 KB picture alone took about half a second to download. But once the bytes arrive quickly, only the round trips are left.
It isn't only this one small page, either. Mike Belshe helped create SPDY, the protocol that became HTTP/2. He loaded popular sites again and again, raising the bandwidth step by step from 1 to 10 Mbps. Then he did the same while cutting the latency. Grigorik's book describes what he found:
- Going from 1 to 2 Mbps nearly halved the load times.
- Past 5 Mbps, each step gained only a few percent. Going from 5 to 10 Mbps made pages just 5% faster.
- Every 20 ms cut from the latency made pages faster by about the same amount, step after step.
So before you pay for a fix, ask which part is bigger. A page with big files needs bandwidth. A page with many small files in a row needs fewer round trips, or shorter ones. Turn the dials yourself, and watch how the split changes:
1,200 ms600 ms600 msWith a 150 ms round trip and 1.6 Mbps, the picture appeared at 1,200 ms. Four round trips in a row took 600 ms of that. Everything else, 600 ms, went on downloading the bytes, mostly the 100 KB picture, and on the browser's own work. Try 20 Mbps, then 100. Then try 150 ms, then 100.
How did the recorder slow the network down? Chrome's DevTools protocol is the set of commands DevTools uses to control the browser. One of them slows a page's network on purpose. The recorder used it to set a minimum wait between sending each request and receiving its reply's headers, and a top download speed.
Real connections also spend round trips setting up, and then speeding up. The next lessons cover those. So real pages pay even more round trips than these loads.
Mobile networks and radio wake-up
Asha is on the bus again, the way she was in the first lesson. Her phone has sat in her pocket for a few minutes. She opens the tea page. Before the first request can even leave, her phone has a job to do: it has to wake up its radio.
A small shop pulls its shutter down whenever nobody is around, to save electricity. When you knock, the shopkeeper has to raise the shutter and switch on the till before serving you. After you leave, they wait a few minutes in case someone else comes, then close up again. If a customer pops in every minute, the shop never gets to close, and the bill climbs.
- In real life: The shutter down and the lights off
- In JavaScript: The radio asleep, to save battery
- In real life: Raising the shutter and switching on the till
- In JavaScript: Waking the radio and getting a slot from the tower
- In real life: Waiting a few minutes before closing again
- In JavaScript: The radio staying awake until a timer runs out
- In real life: A customer popping in every minute
- In JavaScript: A small request every minute, like an analytics ping
A phone's radio is the part that talks to the mobile network. It uses a lot of power while it's awake. So when nothing is being sent, it goes to sleep.
To send again, the radio has to ask the nearest tower for a slot to send in, and wait for the answer. That can take several messages back and forth. The part of the network that hands out the slots is the Radio Resource Controller, or RRC. It decides which phone talks when.
How long the wake-up takes depends on the network. Each row is one kind of network, and how long waking from sleep can take:
| Network | How long can waking take? | Where the number comes from |
|---|---|---|
| 3G | Up to 2 seconds. | High Performance Browser Networking. |
| 4G (LTE) | Under 100 ms. That's the standard's target. | High Performance Browser Networking. |
| LTE-Advanced | Under 50 ms. | High Performance Browser Networking. |
| 5G | No more than 20 ms. That's the minimum requirement, and 10 ms is encouraged. | ITU-R M.2410, the 5G requirements. |
After sending, the radio doesn't fall asleep at once. It stays fully awake until a timer runs out. Then it steps down into a lighter sleep. Waking from a lighter sleep is quicker, under 50 ms on 4G, but it still isn't free.
Two things follow from this:
- The first request after a pause pays for the wake-up, on top of its round trip.
- Small requests every minute or so keep waking the radio and holding it awake, which drains the battery.
Grigorik cites a study by AT&T Labs of a music app. The app sent a small analytics ping once a minute. Those pings were 0.2% of the bytes it sent and received, but 46% of its battery use. That's the shop that never gets to close.
Why does it matter for your pages? Send small requests together, in one batch, rather than one at a time. And avoid asking the server for news on a timer when you can.
Counting round trips in a page load
By now you know that each round trip costs time, and that bandwidth can't remove it. So the useful question is: how many round trips does a page need? You can count them before you measure anything.
Round trips add up fastest when each request has to wait for the one before. It's like a treasure hunt:
At a party treasure hunt, each clue tells you where the next one is hidden. You can't run to the third clue before you've read the second. So the hunt takes one walk per clue, one after another. If one card listed every hiding place, you could fetch them all at once.
- In real life: The first clue, handed to you at the start
- In JavaScript: The HTML page
- In real life: A clue that says where the next one is hidden
- In JavaScript: A file that names the next file, like
teas.jsonnaming the picture - In real life: One walk to fetch a clue
- In JavaScript: One round trip
- In real life: A card that lists every hiding place at once
- In JavaScript: Naming files early, in the HTML, so the browser can ask for them together
The tea page's hunt has four clues: the HTML, app.js, teas.json and the picture. That's the staircase of bars at the top of the lesson. But a first visit has more round trips, before the first clue. The browser has never talked to this server, so it has to set up a connection first:
// A first visit to a new HTTPS site: three steps before the first request.const setup = [ { step: "DNS lookup: find the server's address", roundTrips: 1 }, { step: "TCP connection: open a line to it", roundTrips: 1 }, { step: "TLS 1.3 handshake: agree on a secret code", roundTrips: 1 },]; const setupTrips = setup.reduce((sum, item) => sum + item.roundTrips, 0);console.log(`Setting up costs ${setupTrips} round trips.`);- Line 3 is the DNS lookup. The browser turns the site's name into the server's address, the way you look up a shop's phone number.
- Line 4 is the TCP connection. The browser and the server greet each other before any page data flows, like dialling and hearing "Hello?".
- Line 5 is the TLS handshake. The two agree on a secret code, so nobody in between can read the page. That's the S in HTTPS.
- Line 8 adds up their round trips. Line 9 prints
Setting up costs 3 round trips.
Each step waits for a reply before the next can start. The next three lessons take one step each: DNS lookups, TCP connections and slow start and TLS without the wait.
Now put the setup and the four clues together, and multiply by the round trip:
// A first visit to the tea page: set up, then four requests in a row.const setupTrips = 3; // DNS, TCP and a TLS 1.3 handshakeconst chainTrips = 4; // the HTML, app.js, teas.json, the pictureconst roundTrips = setupTrips + chainTrips; for (const roundTripMs of [20, 100, 150]) { console.log(`${roundTrips} round trips at ${roundTripMs} ms: ${roundTrips * roundTripMs} ms`);}- Line 2 is the setup: 3 round trips. Line 3 is the four requests in a row.
- Line 4 adds them up: 7 round trips.
- Lines 6 to 8 repeat the sum for three round-trip times: 20, 100 and 150 ms.
- It prints
7 round trips at 20 ms: 140 ms,7 round trips at 100 ms: 700 msand7 round trips at 150 ms: 1050 ms.
At 150 ms, a first visit spends more than a second just waiting for replies. That's before a single megabit makes any difference. And on a phone, the radio's wake-up comes on top.
Here is what adds round trips to a page:
- New hosts. A host is a server's name, like completefrontend.com. Each new one needs its own lookup and connection. So a font or a script from another site can cost three round trips before its request even leaves.
- Redirects. A redirect is the server answering "this page has moved". The browser has to ask again at the new address, so each redirect costs at least one more round trip. Redirects covers them.
- Chains. Any file that's only found once another has arrived: a stylesheet that imports another, a font named inside the CSS, or data that a script asks for.
- Big files. A new connection starts by sending a little, then speeds up over several round trips. So a large file takes more than one round trip to arrive.
And here is what removes them:
- reusing a connection that is already open;
- connecting early to hosts the page will need;
- cutting redirects;
- naming important files in the HTML, so the browser finds them sooner;
- caching files, so there's nothing to fetch;
- serving files from closer by, with a CDN.
The system design lesson From URL to pixels follows a page from the address bar to the screen in one go. This module takes it one step at a time, starting with these round trips.
Latency numbers to remember
A few numbers are worth knowing by heart. With them, you can guess a page's waiting time before you measure it. Each row is a fact from this lesson or an earlier one, and the sources at the bottom of the page say where it comes from:
| What happens | How long it takes |
|---|---|
| Light in glass fiber | 200,000 km per second. That's about two thirds of its speed in empty space. |
| New York to London and back, in fiber | 56 ms at best. |
| New York to Sydney and back | 160 ms at best, and 200 to 300 ms over real networks. |
| The delay at which people start to notice lag | 100 to 200 ms. |
| A slower user's connection: the 75th percentile, 2026 | 100 ms per round trip, and 9 Mbps down. |
| Lighthouse's phone network | 150 ms per round trip, and 1.6 Mbps down. |
| Waking a phone's radio | Under 100 ms on 4G, and up to 2 seconds on 3G. |
Two rows come from earlier lessons. The point where people notice lag is from 0.1 seconds, 1 second, 10 seconds. The 75th percentile is from Averages lie: reading distributions. Here it means that a quarter of users have a slower connection than the one in the table.
Here is the habit to take away. When a page feels slow, don't start with bandwidth. Count the round trips the page waits for in a row. Then multiply them by a realistic round trip. For your slower users, that's 100 ms or more.
Latency or bandwidth?
Each task below is held back mostly by one of the two speeds. For each one, ask: is the time going into waiting for replies, or into moving lots of bytes? Then sort it:
- A page that fetches its data, then its picture, one request after another
- A 2 KB JSON reply from a server across the ocean
- A page with small files from five different hosts
- The first request after a phone sat idle
- Downloading a 50 MB app update
- Streaming a 4K video
- Uploading a batch of holiday photos
- A page whose 3 MB background video must arrive before it plays
Sort each task by what mostly decides how long it takes.
Common mix-ups
- "A faster plan makes websites load faster." No, not past a few megabits. After that, most pages wait on round trips, not bytes. Ravi's plan got five times faster, and his page got just 28 ms faster.
- "Latency means the server is slow." No. Latency is travel time. A slow server adds to the wait, but even an instant server is still a round trip away.
- "My ping time is my page load time." No. A ping measures one round trip. A page needs several in a row, plus time to download and draw.
- "Light is too fast to matter." No, not across oceans. New York to Sydney and back takes 160 ms at best, and every round trip pays it again.
- "Small files are free." No. When each one waits for another, four tiny files cost four round trips.
- "5G removes latency." No. It shortens the radio's part. The distance to the server, and the number of round trips a page needs, stay the same.
Practice exercises
Answer first, then use the hints.
The page now has 1,000 KB to download instead of 100. At 5 Mbps, that takes 1,600 ms. What does the second line print?
// The same sum, with one upgrade at a time.
const waitingMs = 600; // 4 round trips of 150 ms
const downloadMs = 1600; // 1,000 KB at 5 Mbps
console.log(`As it is: ${waitingMs + downloadMs} ms`);
console.log(`Double the bandwidth: ${waitingMs + downloadMs / 2} ms`);
console.log(`Halve the round trip: ${waitingMs / 2 + downloadMs} ms`);Double the bandwidth: 1400 ms. With 1,000 KB, the downloading is the bigger part. So now bandwidth matters more: doubling it saves 800 ms, while halving the round trip saves only 300.
The route now goes from New York to San Francisco, 4,148 km away. What does it print?
// Light in glass fiber covers about 200 km every millisecond.
const fiberKmPerMs = 200;
const route = { from: "New York", to: "San Francisco", km: 4148 };
const roundTripMs = (2 * route.km) / fiberKmPerMs;
console.log(`${route.from} to ${route.to} and back: at least ${Math.round(roundTripMs)} ms`);New York to San Francisco and back: at least 41 ms. Grigorik's table rounds the one-way time to 21 ms first, so it lists 42.
This server only speaks TLS 1.2. Its handshake takes two round trips instead of one. What does the last line print?
// The same first visit, to a server that only speaks TLS 1.2.
const setupTrips = 4; // DNS, TCP and a TLS 1.2 handshake, which takes two
const chainTrips = 4; // the HTML, app.js, teas.json, the picture
const roundTrips = setupTrips + chainTrips;
for (const roundTripMs of [20, 100, 150]) {
console.log(`${roundTrips} round trips at ${roundTripMs} ms: ${roundTrips * roundTripMs} ms`);
}8 round trips at 150 ms: 1200 ms. One extra round trip costs 150 ms on every first visit at that distance. TLS without the wait, lesson 4.4, shows how TLS 1.3 saves it.
Look at the recorded loads. Which saved more time before the picture appeared: five times the bandwidth, from 20 to 100 Mbps? Or a round trip 50 ms shorter, from 150 to 100 ms?
The shorter round trip. Going from 150 to 100 ms saved 196 ms of LCP. Going from 20 to 100 Mbps saved 28 ms. The page pays its round trip four times, so every millisecond cut counts four times.
Download the trace at 150 ms and 20 Mbps and open it in the Performance panel. Which other file's request starts at the same moment as the request for app.js?
styles.css. The HTML names both files, so the browser asks for them together. Two requests sent at once share one round trip. That's why the tea page's chain counts four round trips, not five.
The tea page is served from New York. Field data says first visits from Australia have an LCP about a second slower than first visits from New York. Are the extra round trips enough to explain it?
Yes. 7 round trips of at least 160 ms each make about 1.1 seconds. The fix is to serve from closer, with a CDN, or to need fewer round trips. More bandwidth won't help.
Check your understanding
For each question, ask: is the time going into waiting for a reply, or into moving bytes?
Question 1 of 7What does the last line of the upgrades example print?
Read the code, then predict// The same sum, with one upgrade at a time. const waitingMs = 600; // 4 round trips of 150 ms const downloadMs = 160; // 100 KB at 5 Mbps console.log(`As it is: ${waitingMs + downloadMs} ms`); console.log(`Double the bandwidth: ${waitingMs + downloadMs / 2} ms`); console.log(`Halve the round trip: ${waitingMs / 2 + downloadMs} ms`);Choose an answer to see the explanation.
Question 2 of 7What does the speed of light example print?
Read the code, then predict// Light in glass fiber covers about 200 km every millisecond. const fiberKmPerMs = 200; const route = { from: "New York", to: "London", km: 5585 }; const roundTripMs = (2 * route.km) / fiberKmPerMs; console.log(`${route.from} to ${route.to} and back: at least ${Math.round(roundTripMs)} ms`);Choose an answer to see the explanation.
Question 3 of 7What does the second line of the round-trip count print?
Read the code, then predict// A first visit to the tea page: set up, then four requests in a row. const setupTrips = 3; // DNS, TCP and a TLS 1.3 handshake const chainTrips = 4; // the HTML, app.js, teas.json, the picture const roundTrips = setupTrips + chainTrips; for (const roundTripMs of [20, 100, 150]) { console.log(`${roundTrips} round trips at ${roundTripMs} ms: ${roundTrips * roundTripMs} ms`); }Choose an answer to see the explanation.
Question 4 of 7In the recorded loads, why did more bandwidth soon stop helping, while every cut to the round trip helped?
Choose an answer to see the explanation.
Question 5 of 7What does the round-trip time measure?
Choose an answer to see the explanation.
Question 6 of 7Why can the first request after a phone has been idle be slow?
Choose an answer to see the explanation.
Question 7 of 7A first visit to a new HTTPS site uses TLS 1.3. About how many round trips pass before the HTML starts to arrive?
Choose an answer to see the explanation.
Key takeaways
- Bandwidth is how much can flow at once. Latency is how long one message takes to arrive. The round-trip time is there and back.
- Light in fiber covers 200 km every millisecond, so distance sets a floor under every round trip. Only a shorter distance lowers it.
- A load is waiting plus downloading. Bandwidth only shrinks the downloading, so past a few megabits it barely helps a typical page.
- Every millisecond cut from the round trip counts once for each request in the chain.
- An idle phone wakes its radio first: under 100 ms on 4G, and up to 2 seconds on 3G.
- Count the round trips a page waits for in a row: setting up, redirects, and each request that needs another. Then multiply by the round-trip time.
Remember the one-liner.
Count the round trips, then multiply by the round-trip time: that's the wait no bandwidth can buy.
Sources
The facts on this page come from these docs and books:
- Primer on Latency and Bandwidth, High Performance Browser Networking, Ilya Grigorik.
- PerformanceResourceTiming, MDN.
- NetworkInformation: rtt, MDN.
- Primer on Web Performance, High Performance Browser Networking (Mike Belshe's study), Ilya Grigorik.
- Network.emulateNetworkConditions, Chrome DevTools Protocol.
- Mobile Networks, High Performance Browser Networking, Ilya Grigorik.
- Minimum requirements related to technical performance for IMT-2020 radio interface(s), Report ITU-R M.2410, ITU.
- The Performance Inequality Gap, 2026, Alex Russell.
- Network throttling, Lighthouse documentation.
Coming next: DNS lookups. Every new host starts with a lookup, the first of the three setup round trips. You'll see what it costs, and how to hide it.