Every extra second a page takes to load costs you visitors, conversions and search rankings. Performance is no longer a nice-to-have - Google measures it directly, and users abandon slow sites without a second thought. The good news is that most performance problems come down to a handful of well-understood issues, and fixing them rarely requires a rebuild. This guide walks through the highest-impact optimisations, in order of the return they typically deliver.

Core Web Vitals explained

Google's Core Web Vitals are three metrics that capture how a page feels to a real user. They are also ranking signals, so passing them helps both people and search visibility. The targets are:

  • Largest Contentful Paint (LCP) — under 2.5s. How long until the largest visible element (often the hero image or headline) has rendered. It measures perceived load speed.
  • Interaction to Next Paint (INP) — under 200ms. How quickly the page responds to a user's taps and clicks across the whole visit. It measures responsiveness. INP replaced First Input Delay as a Core Web Vital in 2024.
  • Cumulative Layout Shift (CLS) — below 0.1. How much the layout jumps around as things load. It measures visual stability - the frustration of tapping a button that suddenly moves.

These thresholds should be met for the 75th percentile of visits, meaning most of your real users need to have a good experience, not just a test on a fast laptop.

Users judge your business by how your site feels in the first two seconds. Core Web Vitals are simply that judgement, turned into numbers you can act on. - The Solution On IT engineering team

How to measure: lab and field data

You need both kinds of measurement, and they answer different questions:

  • Lab data comes from a controlled test - for example Lighthouse in Chrome DevTools or WebPageTest. It runs the page in a simulated environment, so it is repeatable and perfect for diagnosing a specific problem.
  • Field data comes from real users on real devices and networks, gathered in the Chrome User Experience Report and surfaced in PageSpeed Insights and Google Search Console. This is what Google actually ranks on.

Use lab tools to find and fix issues, but always confirm the win in field data over the following weeks. A page can score well in the lab and still struggle on a mid-range phone on a slow connection.

Optimise your images

Images are the heaviest thing on most pages, so this is usually the biggest single win. There are four things to get right:

Use modern formats

Serve WebP or AVIF instead of JPEG or PNG. They compress far more efficiently at the same visual quality, often cutting file size by a half or more.

Size images correctly and set dimensions

Never ship a 3000px image to display it at 400px. Export images close to their rendered size, and always set explicit width and height attributes so the browser reserves the right space and avoids layout shift (CLS).

Serve responsive images

Use srcset and sizes so each device downloads an appropriately sized file - a phone should never fetch a desktop-sized image.

Lazy-load below the fold - but not the hero

Add loading="lazy" to images below the fold so they load only as the user scrolls. Crucially, do not lazy-load your largest above-the-fold image; that is usually your LCP element, and deferring it makes LCP worse.

html
<!-- Below-the-fold image: responsive + lazy, no CLS -->
<img
  src="photo-800.webp"
  srcset="photo-400.webp 400w, photo-800.webp 800w, photo-1200.webp 1200w"
  sizes="(max-width: 600px) 100vw, 800px"
  width="800" height="600"
  loading="lazy" decoding="async"
  alt="Team reviewing site performance metrics">

Trim and split your JavaScript

JavaScript is the other common culprit. Every kilobyte the browser downloads, parses and executes delays interactivity and hurts INP. A few reliable wins:

  • Remove unused dependencies. Audit your bundle and drop libraries you no longer need - a lighter framework or a native API is often enough.
  • Split by route. With route-based code splitting, each page loads only the code it needs and fetches the rest on demand.
  • Defer non-critical scripts. Analytics, chat widgets and third-party embeds should never block the first paint - load them with defer or after the page is interactive.
  • Minify everything. Ship minified HTML, CSS and JavaScript in production.

Inline your critical CSS

The browser cannot paint until it has the CSS it needs, so a large external stylesheet blocks rendering. Identify the small amount of CSS required to style the above-the-fold content - the critical CSS - inline it in the <head>, and load the rest asynchronously. The page becomes visible far sooner, which directly improves LCP.

Cache aggressively and use a CDN

Caching means visitors don't re-download things that haven't changed. Give static assets long cache lifetimes and use fingerprinted filenames (a content hash in the name) so you can cache them almost forever yet still bust the cache instantly when a file changes. Then put a CDN in front of your site so those assets are served from an edge location close to each visitor, cutting round-trip time dramatically.

http
# Fingerprinted asset - safe to cache for a year
Cache-Control: public, max-age=31536000, immutable

# HTML - always revalidate so users get fresh pages
Cache-Control: no-cache

Compress your text

HTML, CSS, JavaScript and JSON are all text, and text compresses extremely well. Enable Brotli (or gzip as a fallback) on your server or CDN and these files shrink by roughly 70–80% over the wire - a large win for effectively no effort. Most CDNs and modern servers offer this with a single setting.

Optimise your fonts

Web fonts are a frequent, easily-missed cause of both slow rendering and layout shift. Four steps keep them cheap:

  • Use font-display: swap so text renders immediately in a fallback font instead of staying invisible while the web font loads.
  • Preconnect to the font host to open the connection early and shave off latency.
  • Subset your fonts to include only the characters and weights you actually use.
  • Self-host where practical to avoid an extra third-party connection.

Performance work like this is a core part of how we build - you can read more on our web development service page, and see how it fits into a wider system in our web application architecture guide.

Common mistakes to avoid

  • Lazy-loading the hero image. Deferring your LCP element is the most common self-inflicted performance wound.
  • Images without dimensions. Omitting width and height causes layout to jump as images load, wrecking CLS.
  • Shipping everything up front. Loading all your JavaScript on the first page delays interactivity everywhere.
  • Optimising only in the lab. A green Lighthouse score means little if real users on mid-range phones still have a poor experience.
  • Unbounded third-party scripts. Every widget and tag you add runs on your users' devices and can quietly undo your gains.

Best practices

  1. Set a performance budget. Agree limits for page weight and Core Web Vitals, and hold every change to them.
  2. Optimise images first. Modern formats, correct sizing and responsive srcset usually give the biggest return.
  3. Prioritise the critical path. Inline critical CSS, defer the rest, and never block the first paint.
  4. Cache and compress at the edge. Long cache lifetimes, fingerprinted assets, a CDN and Brotli are near-free wins.
  5. Measure with real users. Track field data continuously so regressions show up before they cost you.

Frequently asked questions