Document request latency: how to fix all three checks
Every file on your page waits for the HTML. What the three checks under the notice mean, and the fix for WordPress, Shopify, Cloudflare and your own server.
- Good ≤ 0.8 s
- Needs improvement ≤ 1.8 s
- Poor > 1.8 s
What do “Had redirects” and “Server responded slowly” mean?
Document request latency, the Lighthouse notice that starts with "Your first network request is the most important", replaced Reduce initial server response time. Both lines mean your HTML arrives late, through a redirect or a slow server, and every other file waits for it. Link to the final https address, let a page cache answer in under 600 ms and turn on gzip or Brotli.
Just want the quick fix? Jump to WordPress, Shopify, Cloudflare or Apache and Nginx.
What does each Document request latency check measure?
The notice is about one file: the HTML of the page you tested, the first request the browser makes. Lighthouse says: "Your first network request is the most important. Reduce its latency by avoiding redirects, ensuring a fast server response, and enabling text compression." Under it are three checks:

The test page before any fix, with the settings PageSpeed Insights uses.
- "Had redirects (3 redirects, +271 ms)": the address you tested sent the browser on to another address before it sent the page, and one redirect is enough for the cross. If you think your site has none, look at the address you tested: typed without https or www, it is sent on to the final address, like every visitor who types it or follows an old link. Test the final address as well; your field data shows which redirects your visitors meet.
- "Server responded slowly (observed 1304 ms)": the time between sending the request and the first byte of the answer, measured once in this run. The check fails above 600 ms. Aim for about 100 ms; for that you need a page cache. This wait is one part of your Time to First Byte.
- "No compression applied": the HTML came without gzip, Brotli or zstd. Only the HTML counts, so a server that compresses your stylesheets and scripts but not the page itself fails this check.
Red means Lighthouse expects the first content (FCP) and the largest element (LCP) to appear sooner without the redirects or the slow server. With only the compression cross the notice is orange, and while compression fails, "Est savings" shows kilobytes, even next to a slow server. Unscored: the notice adds nothing to the score itself, but FCP and LCP do, and both wait for the HTML. Before Lighthouse 13 the three checks were separate audits: Avoid multiple page redirects, Reduce initial server response time and Enable text compression.
Why does the whole page wait for the HTML?
Your visitor taps a link and looks at the previous page, or a white screen, until the HTML arrives. Then the page appears.

Before

After
The test page, a theatre's What's on page, on a phone connection, 2 seconds after the tap.
The stylesheets, scripts and photos are named inside the HTML, and the fonts inside those stylesheets, so none of them can start before it arrives (for what loads after it, see Network dependency tree). Every millisecond the HTML is late, FCP and LCP are late too.
I measured it on that theatre page, set up like a WordPress site without a page cache and opened through the address without www and https. The phone connection had a 150 ms round trip and 1.6 Mbps, and the times count from the tap:
| Change | FCP | HTML complete |
|---|---|---|
| Before | 3.72 s | 3.64 s |
| Final address, no redirects | 2.78 s | 2.70 s |
| Plus a page cache | 1.56 s | 1.44 s |
| Plus Brotli | 0.81 s | 0.54 s |
The page cache did the most: the server answered in 40 ms instead of 1.3 seconds. On the phone connection the three redirects took almost a second, where the report showed +271 ms: Lighthouse times them on its own fast connection, and on a phone every redirect is a new request with its own round trips. Brotli shrank the 197 kB HTML to 19 kB, which took 0.9 seconds off its download. According to the State of Web Vitals, of sites with a TTFB over 1.8 seconds on phones, 14% pass LCP, against 94% with a good TTFB.
Why is the observed server time different on every run?
"Observed" means Lighthouse measured it on one load, from the machine that ran the test. When the page cache was empty for that load (just cleared after a plugin update, or expired), the server built the page itself and the check failed. On the next run the cache answers and the check is green, a common reason for a score that changes between runs.
Some visits skip the cache every time: logged-in visitors, the cart, and links with a query string the cache doesn't know, such as an ad's gclid. Lighthouse tests your clean address from one place, while a visitor far away also waits longer for the same server, so your field data, what real visitors get, is what counts.
A red server check next to a fast FCP in the same report is possible: the report calculates FCP with a model, while the server time is what it really saw.
How do you fix Document request latency?
Start with the check that shows the most time. On most sites that is the server, and the fix is a page cache. Then the redirects, then compression, which is usually one setting.
WordPress
Without a page cache WordPress runs PHP and database queries to build the page for every visitor. A page cache keeps the finished HTML and sends it straight away. The closer to the visitor it sits, the faster: cache the HTML at your CDN first (Cloudflare below), then your host's page cache (most managed WordPress hosts have one), then a cache plugin such as my own WP Core Web Vitals (Fast cache), WP Rocket, or LiteSpeed Cache on a LiteSpeed server. Turn on the cache's preload, so each page is in the cache before the first visitor asks for it.
To see whether a page comes from the cache, open it logged out in a private window: most caches add a response header with HIT or MISS, which DevTools shows. Let the cache treat links with tracking parameters as the same page (WP Rocket and LiteSpeed Cache have a list for that). A new plugin that sets a cookie on every page can undo all this, and so can a cache that empties on every update without a preload. For pages that can't be cached, request duration covers the server side.
For the redirects: under Settings, General, both the WordPress Address and the Site Address should be the final address: https, with or without www exactly as your pages show in the address bar. Point your menus, internal links and ads at that exact address, with the trailing slash your permalinks use. Let each rule in a redirect plugin point straight at the final page.
Compression is your host's setting and usually on. If the HTML comes uncompressed, ask the host for gzip or Brotli on text/html; a cache plugin can only switch it on through .htaccess on Apache and LiteSpeed.
Shopify
Shopify runs the server and its cache, and it compresses the HTML. The server check passes on almost every store because Shopify sends the start of the page right away. A slow theme shows up later, in FCP and LCP: LCP breakdown shows where. The redirects are yours. Under Settings, Domains, choose the primary domain and link to it everywhere: ads, emails, social profiles. Automatic redirection in Online Store, Preferences sends visitors from another country to their own market with an extra redirect on their first page; a banner that offers the switch saves them that wait.
Cloudflare and other CDNs
Once a Cache Rule sets your HTML to "Eligible for cache", Cloudflare sends it from a server close to the visitor, without a request to your own server. Set that rule up yourself: skip the cache for logged-in visitors, the cart and the checkout (by their cookies and paths), and decide what happens with links that carry tracking parameters, which otherwise each get a copy of their own. Then check in your field data which visits still wait on your server and adjust the rule. APO, Cloudflare's ready-made page cache for WordPress, works the same way, with fewer cache hits than a rule tuned to your own site.
Cloudflare compresses the HTML for your visitors by default. Set SSL/TLS to Full (strict), or Full. With Flexible, Cloudflare talks to your server over http; a server that redirects http to https then answers every request with that redirect, and the visitor ends up in a redirect loop.
Apache and Nginx
Send http and the bare domain (example.com without www) to the final address in one redirect. On Apache, at the top of .htaccess, above the WordPress block:
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [L,R=301]
<IfModule mod_brotli.c>
AddOutputFilterByType BROTLI_COMPRESS text/html text/css text/javascript application/javascript
</IfModule>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/css text/javascript application/javascript
</IfModule>
On Nginx, gzip goes in the http block of nginx.conf: switch it on, and set gzip_proxied so requests that come through a proxy are compressed too (text/html is always included):
server {
listen 80;
server_name example.com www.example.com;
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/ssl/example.com.crt;
ssl_certificate_key /etc/ssl/example.com.key;
return 301 https://www.example.com$request_uri;
}
gzip on;
gzip_proxied any;
gzip_types text/css text/javascript application/javascript application/json image/svg+xml;
Brotli on Nginx needs the ngx_brotli module. A page cache in the server itself (Nginx FastCGI cache, Varnish) answers before PHP starts.
Next.js and other frameworks
A page rendered for every request waits for its data each time. Where the content allows it, render it once and refresh it on a schedule:
// app/whats-on/page.js
export const revalidate = 300; // build the page once, rebuild at most every 5 minutes
Reading cookies or headers in a page makes it render per request again. Write your links with or without the slash, the way your trailingSlash setting expects, or Next.js adds a redirect.
Redirects you can't remove
A link shortener, a social network's link wrapper or an ad platform's click tracker adds a redirect on someone else's server. Make sure each of them points at your final address, so theirs is the only redirect.
How do you check the redirects, the server time and the compression yourself?
Run Lighthouse a few times, in the same way each time, with the address your visitors use. To see each check without a report, ask for the page the way a browser does:
curl -sIL -H "Accept-Encoding: br, gzip" http://example.com/page | grep -iE "^HTTP|^location|content-encoding"
Every location line is a redirect, and the last response should show content-encoding: br or gzip. Leave out the Accept-Encoding header and servers answer uncompressed, even with compression on. In Chrome DevTools, the Network panel shows the HTML request's wait under Timing as "Waiting for server response", and the Performance panel marks the notice's three parts on that request:

A DevTools recording of the test page before the fixes, on a phone connection.
For your real visitors, CoreDash splits TTFB on phones into its parts per page. The orange part, Waiting + Redirect, grows with the redirects before the page; the green part, Request, with the time your server takes. Look for pages where one of those two is large, and check after the fix that it has shrunk on the same pages. Search Console takes up to 28 days to show it.

Some pages can't be cached, such as a shop's cart or a members area, and some hosts are slow before WordPress even starts. Then the work is on the server itself, and that is what we look at together in a power hour: your own TTFB, page by page, and what your server waits for.

Need a faster site?
I'm Arjen, and I've been fixing slow sites for 17 years. If you're running into issues you can't fix yourself, send me your URL and let's have a chat.
Send me your URL
Why isn't our fix working?
Sometimes the CDN still serves the old HTML, or the fix went into the desktop template and mobile uses another one. Send me your URL and the problem, and I reply with a few times. I check your field data first, then we spend one hour on your site, and within a day you have my notes in writing. €350 excl. VAT.
Send me your URLNo developer to build the fix? I do the work myself, on a copy of your site.