How to speed up a website: the order that pays
Most speed advice is a list of thirty items with no order. On a small product site, six changes account for nearly all the gain, and they have a sensible sequence. Measure first, work down the list, and check the field data four weeks later.
By Théophile Louvart, founder of Porteur · Updated 15 September 2026 · Markdown
Measure first, and measure the right thing
Two kinds of number exist and they answer different questions. Field data is what real Chrome users experienced, at the 75th percentile over 28 days, and it is what Google uses. Lab data is one simulated run on a mid-range phone over a throttled connection, and it is what tells you why.
- Largest Contentful Paint: good up to 2.5 s, poor above 4 s. The big thing at the top of the page.
- Cumulative Layout Shift: good up to 0.1, poor above 0.25. The page moving under a reader's thumb.
- Interaction to Next Paint: good up to 200 ms, poor above 500 ms. The wait after a tap.
Open PageSpeed Insights on the page you care about. The top half is the field assessment, the half that counts. The bottom half is a Lighthouse run with the opportunities. Write down the three vitals before you touch anything, because you will want them in four weeks.
The order of work
| Change | What it moves | Effort |
|---|---|---|
| The hero image | LCP, often by seconds | An hour |
| Render-blocking CSS and JavaScript | First paint, and LCP behind it | An afternoon |
| Fonts | First paint, and CLS when they swap | An hour |
| Third-party scripts | INP, total blocking time, and the paint | An hour to decide, minutes to remove |
| The server and the CDN | Time to first byte, which every other number inherits | A day, once |
| The JavaScript bundle | INP and blocking time | The longest job, do it last |
Work top to bottom and re-measure after each. A page that was poor is usually fine after the first three, and the last two are where the remaining seconds hide.
The hero image, the single biggest win
On most marketing pages the largest element is an image at the top. It is the LCP element, and three mistakes make it slow.
Never lazy-load it
loading="lazy" on the element above the fold delays the very thing being measured. Lazy loading is for what is below.
Give it priority
fetchpriority="high" on the hero image tells the browser to fetch it before the rest. If it is a CSS background, preload it, because the browser cannot see it in the HTML.
Serve the right size and format
AVIF or WebP, with srcset and sizes so a phone does not download a desktop image. A hero that weighs a few hundred kilobytes instead of two megabytes paints seconds earlier.
Reserve its space
width and height attributes, or an aspect-ratio in CSS, so nothing jumps when it arrives. That is the CLS half of the same fix.
<img src="/hero.avif"
width="1200" height="630"
fetchpriority="high"
alt="The report open on a laptop">Render-blocking CSS and JavaScript
A stylesheet in the head stops the browser painting until it arrives. A synchronous script stops it parsing. Lighthouse lists both under render-blocking resources, and the fix is mostly attributes.
- Add defer to scripts that do not need to run before the paint, which is nearly all of them. Modules defer by default.
- Inline the small amount of CSS the first screen needs, and load the rest without blocking.
- Remove the CSS nobody uses. A framework shipped whole on a page using a tenth of it is the usual finding.
- Avoid @import in stylesheets: it serialises requests that could have run in parallel.
Fonts: one family, self-hosted, loaded first
A web font from a third-party host costs a DNS lookup, a connection, a stylesheet and then the font file, all before the first word appears. Self-hosting removes three of the four.
- Self-host the files in WOFF2 and serve them from your own domain or CDN.
- font-display: swap so text is readable while the font loads, with a fallback whose metrics are matched so the swap does not shift the layout.
- Preload only the one face used above the fold. Preloading everything is the same as preloading nothing.
- Subset to the characters you use, and prefer one variable font to four static weights.
- A system font stack costs nothing at all, and on a product site nobody notices.
Third-party scripts, the weight you did not write
List what is on the page
Lighthouse has an audit for the impact of third-party code. Most small sites find analytics, a chat widget, a consent tool, a video embed and a tag manager.
Remove what nobody reads
The fastest script is the one you delete. A chat widget nobody answers and a heatmap tool from last year are both pure cost.
Delay what can wait
Analytics can start when the browser is idle. A page view captured a second later is the same page view.
Use a facade for embeds
A video embed loads a player and a tracking bundle before anyone presses play. A thumbnail that loads the real embed on click saves all of it.
Preconnect to what must load early
For the few origins that are genuinely needed on the first screen, a preconnect saves the handshake.
The server and the CDN
Time to first byte is the delay every other metric inherits. It includes redirects, the lookup, the handshakes and your server's own work, and it is the one number a CDN fixes almost entirely for distant visitors.
- Put a CDN in front of the origin. It serves from the location closest to the visitor and removes most of the first-byte time.
- Cache the HTML where you can: a short cache with revalidation, or a stale-while-revalidate window at the edge. Static pages should never be rebuilt per request.
- Give hashed static assets a year of immutable caching. They never change, and the hash changes when they do.
- Serve Brotli for text, gzip as the fallback.
- Enable HTTP/2, and HTTP/3 where the CDN offers it. Both are a setting, not a code change.
- Remove redirect chains on the entry points. Two hops before the first byte is two round trips a visitor waits through.
The JavaScript bundle, last and longest
This is where the remaining Interaction to Next Paint lives. It is also the work that takes weeks rather than hours, which is why it comes last: the five changes above usually take a page from poor to good on their own.
- Ship less of it: split by route so a landing page does not load the dashboard's code.
- Render the content on the server so the browser is not building the page and hydrating it at once.
- Break long tasks so the main thread is free when someone taps.
- Keep the DOM small. A page with tens of thousands of nodes is slow to interact with whatever the bundle weighs.
How to tell whether it worked
Re-run the lab test immediately
Same page, same tool. The lab number should move the moment you deploy. Run it twice: scores vary between runs.
Wait for the field data
The field assessment is a 28-day window of real visits. Nothing you changed today is fully reflected until four weeks of visits have passed.
Read the Core Web Vitals report
In Search Console, the report groups URLs by template. A group moving from Needs improvement to Good is the fix landing across every page built from that template.
Keep a note of what you changed and when
Without dates you cannot attribute the movement, and in four weeks you will not remember the order.
A fixed page looks like this: LCP under 2.5 s in the field, CLS near 0.1, INP under 200 ms, and a lab report whose remaining opportunities are worth less than an hour each.
Questions
Core Web Vitals are a ranking signal, measured on field data at the good thresholds, and Google has said it is a smaller factor than relevance and content quality. Speed also affects conversion and crawling, which is why it is worth an afternoon regardless.
The score is a diagnostic. It varies between runs and is not what Google ranks on. Aim for the field thresholds instead: LCP up to 2.5 s, CLS up to 0.1, INP up to 200 ms.
The mobile test simulates a mid-range phone on a throttled connection, and Google indexes the mobile version of pages. A page that is fine on a laptop can be slow on a phone because of CPU, JavaScript and images sized for a large screen.
The lab numbers change immediately. The field assessment uses a 28-day window of real visits, so the reports in Search Console take about four weeks to reflect a fix fully.
If your visitors are far from your server, yes: it removes most of the time to first byte, and most hosting platforms include one. If everything is cached and your audience is local, it matters less.
The hero image. It is the largest element on most pages, so it is what Largest Contentful Paint measures, and the three fixes (do not lazy-load it, give it priority, serve a modern format at the right size) take about an hour.
Check my site, free
Paste your URL and the free check measures your home page the way Google does, on a phone, and names the three changes that would give back the most time.
- Free check, no card
- Read-only, your own accounts
- Readable by your agent
Read next
- GuideCore Web Vitals for a product site: the three numbers
- GuideLargest Contentful Paint: what slows it and what fixes it
- GuideRender-blocking resources: what blocks the first paint and how to unblock it
- GuideWeb fonts and page speed: load one face, and load it first
- GuideThird-party scripts: the page speed you gave away
- GuideImage optimisation for page speed: the hero image and everything below it
- GuideHow to read PageSpeed Insights: field data first, then the score
- Free toolCore Web Vitals checker