Skip to content

Fast on a real phone: measuring and fixing page speed

A site that feels fast on an office laptop can feel slow on a mid-range phone on mobile data, which is how most customers see it. How to measure speed the way customers experience it, what the Core Web Vitals mean, and the fixes that make the biggest difference.

Most websites are built and checked on fast computers with good connections, and most customers see them on phones, often not new ones, often on mobile data. The gap between those two experiences is where speed problems hide: the site looks instant to the people who built it and slow to the people who pay for it.

Speed matters for more than patience. Slow pages lose visitors before they see anything, and Google uses page experience in how it ranks sites. This article is about measuring speed the way customers actually experience it, what the numbers mean, and the handful of fixes that make most of the difference.

Measure like your customers load it

There are two kinds of speed data, and both are useful:

  • Field data comes from real visitors on real devices. Google collects it from Chrome users and shows it in Search Console and in PageSpeed Insights, when a site has enough traffic. It is the truth, but it arrives slowly and cannot tell you why something is slow.
  • Lab data comes from a test run on demand, such as Lighthouse in Chrome’s developer tools. It is immediate and detailed, and it is only a simulation.

The habit that matters is to run lab tests the way customers load the site: with mobile emulation and a throttled network and processor, not on the developer’s unthrottled machine. A page that scores well only without throttling is not fast; it is being tested on the wrong device.

What the Core Web Vitals mean

Google summarises page experience in three measures, the Core Web Vitals:

  • Largest Contentful Paint (LCP): how long until the main content, usually the biggest image or heading, is visible. Good is under 2.5 seconds.
  • Interaction to Next Paint (INP): how quickly the page responds when someone taps or types. Good is under 200 milliseconds.
  • Cumulative Layout Shift (CLS): how much the page jumps around while it loads, the button that moves just as you tap it. Good is under 0.1.

Each one points at a different kind of fix, which is why it is worth knowing which one is failing before changing anything.

Images

Images are the most common cause of a slow first view, and the easiest to fix:

  • Serve each image at the size it is shown. A 4000-pixel photo displayed at 400 pixels wastes most of what the phone downloads.
  • Offer several sizes and let the browser choose, with srcset and sizes.
  • Use modern formats such as WebP or AVIF, which are much smaller than JPEG and PNG at the same quality.
  • Give every image its width and height in the markup, so the browser reserves its space and the page does not jump when it arrives. This alone fixes most layout shift.
  • Load images below the first screen lazily, and do not lazy-load the main image at the top, which should load first, and can be preloaded.

Fonts

Custom fonts are a quiet cause of slow and jumpy pages. The browser has to download them before it can show text in them. Three habits help:

  • Use few font files: every weight and style is a separate download.
  • Preload the one or two fonts used in the first screen, and serve them in the WOFF2 format.
  • Use font-display: swap, so text appears in a fallback font immediately and switches when the custom font arrives, and choose a fallback with similar proportions so the switch does not shift the layout.

JavaScript

On a mid-range phone, JavaScript is often the real bottleneck: not downloading it, but running it. A page can arrive quickly and still not respond to a tap for seconds while the phone works through its scripts, which is exactly what INP measures.

  • Send the content as HTML from the server, rendered there, rather than building it in the browser after a large script has loaded.
  • Split the JavaScript so each page loads only what it needs.
  • Look hard at what every library costs. A date library, a carousel or an animation package can each weigh more than the page’s own code.

Third-party scripts

Chat widgets, analytics, advertising tags, heatmaps and social embeds are often the heaviest things on a page, and nobody on the team wrote them. Each one downloads its own scripts, sometimes from several servers, and runs them on the customer’s phone.

Make a list of every third-party script on the site, what it is for, who uses its data and what it costs in speed. Some will turn out to be unused leftovers. The rest can usually be loaded later, after the page is usable, rather than first.

The server and the network

The first byte has to arrive before anything else can happen. A slow server response delays everything after it:

  • Cache what does not change for every visitor, at the server and, for static files, at a CDN close to your customers.
  • Make sure the slowest database queries behind your main pages are known and fast.
  • Serve files compressed, with long cache lifetimes for files whose names change when their content does.

Reading a Lighthouse report

A Lighthouse report can be overwhelming. Read it in this order:

  1. The three Core Web Vitals and the overall score, with the device set to mobile.
  2. The screenshot strip, which shows how the page appears over time. It often explains the numbers at a glance: a white screen for two seconds, a layout that jumps.
  3. The "Largest Contentful Paint element": which element it was. If it is an image, the image is the first thing to fix.
  4. The opportunities list, sorted by estimated saving. The top two or three usually matter; the long tail rarely does.

Run it three times and look at the middle result. Single runs vary more than people expect.

An image, done properly

Most of the image advice fits in one element. An image offered at several widths, in a modern format, with its dimensions reserved:

<img
  src="/media/product-800.webp"
  srcset="/media/product-400.webp 400w,
          /media/product-800.webp 800w,
          /media/product-1600.webp 1600w"
  sizes="(max-width: 700px) 100vw, 700px"
  width="1600" height="900"
  alt="A blue mug on a wooden table"
  loading="lazy" decoding="async">

The sizes attribute tells the browser how wide the image will be shown, so it can pick the smallest file that is sharp enough. width and height give the proportions, so the space is reserved before the file arrives. For the main image at the top of the page, drop loading="lazy" and consider preloading it instead.

Caching, in two lines

Files whose names change whenever their content changes, the scripts and stylesheets a modern build produces, can be cached by browsers for a year. Pages themselves usually should not be, or only briefly. The headers look like this:

# /assets/app.3f9c2a.js   (name changes when content changes)
Cache-Control: public, max-age=31536000, immutable

# /products/blue-mug      (a page)
Cache-Control: public, max-age=0, must-revalidate

Getting this right means a returning visitor downloads almost nothing but the page itself, and a new release is still picked up immediately.

The database behind the page

When the server is slow to answer, the cause is usually the database, and the most common single cause is a pattern called N+1: a page that lists 50 products runs one query for the list, then one more query per product to fetch its price or image. Fifty-one queries where two would do.

The fix is to load the related data in one go, and the way to find these is to log the number of queries per page in development. A page that runs hundreds of queries is not unusual in a system that grew over years, and it is often the cheapest large speed-up available.

A budget, so it stays fast

Speed tends to degrade one small change at a time: a new script here, a larger image there. A speed budget makes the degradation visible. Set limits, for example the total size of scripts on the main pages and a minimum Lighthouse score on a throttled phone profile, and check them automatically on every change, the same way tests are checked. A change that breaks the budget is not necessarily wrong, but it becomes a decision someone makes, rather than something that just happens.

Smaller fonts

Fonts deserve one more practical note. A font file often contains characters for dozens of languages the site never uses. Subsetting it, keeping only the characters needed, for example Latin and Cyrillic for a Bulgarian and English site, can cut its size several times over. Combined with self-hosting the files rather than loading them from a third-party service, it removes a connection to another server from the critical path of every page.

Why it is worth the effort

It is worth being precise about why speed matters, because it decides how much effort it deserves. A slow page costs in three ways. Visitors leave before the page appears, and the ones who leave are disproportionately on phones and slower connections, which often means new customers rather than loyal ones. Visitors who stay find the site harder to use: every tap that takes a second to respond is a small reason to give up. And search engines use page experience among many signals when ranking, so a slow site competes with one hand tied.

None of that means chasing a perfect score. A page that loads its main content in under two and a half seconds on a mid-range phone, responds to taps immediately and does not jump around is fast enough for almost any business. Past that point, the effort is usually better spent elsewhere.

When the lab and real visitors disagree

Lab tests and real visitors often disagree, and it is worth knowing why before trusting either:

  • The lab tests one page, once, from a clean browser. Real visitors arrive with a warm cache, or with twenty browser tabs open, or on a phone that is also downloading updates.
  • The lab tests the page as it loads. INP, the responsiveness measure, depends on what people actually tap, which a lab test cannot know, so lab tools can only estimate it.
  • Real visitors include the slowest phones and the worst connections your customers have. A lab test on a simulated mid-range phone is a guess at the middle.

Use the lab to find and fix problems, and the field data to confirm that the fix reached real people. If they disagree, the field data wins.

Rendering on the server

Where the page is built matters as much as what is on it. A page rendered on the server arrives as finished HTML: the browser can show the content as soon as it arrives. A page built in the browser arrives as an empty shell plus a script, and the content appears only after the script has downloaded and run, which on a mid-range phone can take seconds.

That is why modern frameworks render on the server first and then make the page interactive in the browser, a step called hydration. It gives the best of both, as long as the amount of JavaScript needed for hydration is kept in check. A page whose content is visible quickly but which cannot be tapped for three seconds while it hydrates has only moved the problem.

a speed checklist
[ ] Measured on a throttled mobile profile, three runs
[ ] Main image: right size, modern format, dimensions set, preloaded
[ ] Other images: srcset, sizes, lazy-loaded below the fold
[ ] Fonts: few files, WOFF2, subset, preloaded, font-display: swap
[ ] Content rendered on the server
[ ] JavaScript split per page, heavy libraries questioned
[ ] Third-party scripts listed, unused ones removed, the rest deferred
[ ] Long cache lifetimes on fingerprinted files
[ ] Slowest database queries on the main pages known
[ ] A speed budget checked on every change
where to start
  1. Measure on a throttled phone profile and note which of the three vitals fails.
  2. If LCP fails: the main image, the fonts, the server response.
  3. If CLS fails: image dimensions, fonts, anything inserted above existing content.
  4. If INP fails: JavaScript, and third-party scripts first.
  5. Measure again after each change, not after all of them, so you know which one helped.

Is your site slow on a phone?

Send me the address and I will tell you where the time goes.

Discuss your project