A one-second delay in page load time reduces conversions by 7% on average. For e-commerce that translates directly to lost revenue; for content sites it means higher bounce rates and lower time-on-page signals that feed back into rankings. The good news: most of the speed gap between a slow site and a fast one comes down to a handful of fixable issues — and most of them are free to implement.
This checklist organises 18 improvements by impact tier. Fix the high-impact items first; the return on effort drops as you work down the list, but each fix compounds with the others. Run the Page Speed Inspector before you start to get a concrete baseline, then re-run after each tier to measure the gain.
Key Takeaways
- LCP (Largest Contentful Paint) is the Core Web Vital most affected by speed optimisations — target under 2.5 seconds
- Image optimisation (compression + modern formats + correct sizing) is the single highest-impact fix for most sites
- Render-blocking scripts and stylesheets delay everything — defer non-critical JS, move blocking scripts to the end of
<body> - A CDN reduces TTFB for geographically distributed visitors by serving pages from edge nodes near the user
- Run the Page Speed Inspector before and after each fix to measure the actual improvement
High-impact fixes (do these first)
These six items account for the majority of speed gains on most sites. If you only have time for one pass, start here.
1. Compress images
Unoptimised images are the most common speed issue — and the easiest to fix. Compress all images to the minimum file size that maintains acceptable visual quality. A photograph that looks identical at 120 KB and at 1.2 MB is wasting 1.1 MB of bandwidth on every page load. Tools: Squoosh (browser-based, free), ImageOptim (Mac app, batch processing), Sharp (Node.js library for server-side processing pipelines).
Typical reduction: 40–80% file size with no visible quality loss at standard display sizes.
2. Use modern image formats
WebP delivers 25–35% smaller files than JPEG at equivalent quality. AVIF goes further — 40–50% smaller — but has slightly lower browser support (all major browsers as of 2024, but check your analytics for legacy traffic). Serve WebP with a JPEG fallback using the <picture> element:
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="...">
</picture>
3. Correctly size images
Serving a 2400×1600 px image in a 600 px column wastes 94% of the pixels — the browser downloads them all, then scales the image down. Serve images at the dimensions they'll actually be displayed. Use srcset and sizes for responsive serving so mobile devices receive smaller files:
<img src="hero-600.jpg"
srcset="hero-600.jpg 600w, hero-1200.jpg 1200w, hero-2400.jpg 2400w"
sizes="(max-width: 768px) 100vw, 50vw"
alt="...">
4. Enable compression (gzip/Brotli)
Text-based resources — HTML, CSS, JavaScript, JSON, SVG — compress 70–90% with gzip or Brotli. Most web servers support this natively; it is often just a config flag. Brotli compresses roughly 15–20% better than gzip and is supported by all modern browsers. Check your server config or CDN settings — many CDNs enable Brotli by default.
Verify with the Page Speed Inspector: the Compression tile will report br, gzip, or none.
5. Add server-side caching
Pre-rendered or cached HTML responses eliminate database query time from TTFB. Every millisecond the server spends querying a database before it can send the first byte adds directly to LCP. Options: Redis or Memcached for application-level caching of rendered HTML or database results; CDN full-page caching for pages that are the same for all visitors (marketing pages, blog posts, tool landing pages).
6. Use a CDN
Serving from a single origin means a visitor in Sydney waits for packets to travel to your server in Frankfurt and back — potentially 300–400 ms of latency before a single byte arrives. A CDN serves static assets (images, CSS, JS) and — where caching allows — full HTML pages from edge nodes near each visitor. For geographically distributed audiences, a CDN is the highest-leverage single infrastructure change you can make.
Medium-impact fixes
These six items deliver meaningful gains but require more implementation care. They're worth doing once the high-impact tier is clean.
7. Defer non-critical JavaScript
Scripts loaded in <head> without defer or async block HTML parsing until they've been downloaded, parsed, and executed. A 200 KB analytics bundle loaded this way can delay first paint by 500–800 ms on a slow connection. Add defer to scripts that don't need to run before the page renders, or move them to the bottom of <body>. Use async only for truly independent scripts (like analytics) — defer preserves execution order, async does not.
8. Preload the LCP image
The browser discovers the hero image only after it has parsed the HTML far enough to find the <img> tag — by which point CSS, render-blocking scripts, and other resources may already be queued. Add a <link rel="preload"> in <head> to move image discovery to the earliest possible point in the load sequence:
<link rel="preload" as="image" href="/images/hero.webp" fetchpriority="high">
Do not add loading="lazy" to the LCP image — lazy loading and fetchpriority="high" conflict and hurt Core Web Vitals.
9. Preconnect to third-party origins
Every third-party domain your page loads resources from requires DNS resolution, TCP handshake, and TLS negotiation before the first byte can be transferred — typically 100–300 ms per origin. Add <link rel="preconnect"> for origins you know you'll need (Google Fonts, CDNs, analytics endpoints) to run this overhead in parallel with other work:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10. Eliminate render-blocking stylesheets
CSS loaded in <head> blocks rendering — the browser will not paint anything until all stylesheets have been downloaded and parsed. For CSS that is not needed for the initial viewport, load it asynchronously:
<link rel="stylesheet" href="/css/non-critical.css"
media="print" onload="this.media='all'">
<noscript><link rel="stylesheet" href="/css/non-critical.css"></noscript>
For critical above-fold styles, consider inlining them in <style> tags so no external request is needed for the initial render.
11. Set proper cache headers
Static assets that don't change (images, versioned CSS, versioned JS) should be served with long cache headers so returning visitors don't re-download them:
Cache-Control: max-age=31536000, immutable
HTML pages need a shorter cache with revalidation support — use Cache-Control: public, max-age=3600, stale-while-revalidate=86400 so CDNs serve stale content while revalidating in the background. This eliminates the perceived wait time for the user while keeping content fresh.
12. Enable HTTP/2
HTTP/1.1 browsers open 6 parallel connections per domain, so large pages with many resources queue requests. HTTP/2 multiplexes all requests over a single connection, eliminating the queue. It also uses header compression (HPACK) and supports server push. HTTP/2 is enabled by default on most modern web servers (nginx ≥ 1.9.5, Apache ≥ 2.4.17) and all major CDNs — verify with the Page Speed Inspector's HTTP Version tile.
Lower-impact but important fixes
These six items contribute incremental gains. They're most valuable on pages that have already been optimised through the first two tiers.
13. Optimise web fonts
Web fonts loaded from an external CDN are a common source of render-blocking behaviour. Use font-display: swap to show fallback system text while the font loads rather than showing invisible text. Preload critical font files. Self-hosting fonts eliminates the third-party DNS + TCP + TLS round-trip entirely — for sites where fonts are performance-critical, this is worth the hosting overhead.
14. Lazy load below-fold images
Images below the initial viewport don't need to be loaded immediately. Add loading="lazy" to push their download until the user scrolls near them:
<img src="below-fold.jpg" loading="lazy" width="800" height="500" alt="...">
Never add loading="lazy" to the LCP (hero) image — it directly hurts your LCP score. The Page Speed Inspector flags images that are missing lazy loading where it would help.
15. Reduce DOM size
Google's threshold for a healthy DOM is under 1,400 nodes; pages with 5,000+ nodes see measurable rendering slowdowns, especially on mobile. Large DOMs are usually the result of deeply nested components or content that is rendered but hidden with CSS. Audit with Chrome DevTools → Lighthouse → DOM Size, or the Page Speed Inspector's DOM Nodes tile.
16. Remove unused CSS
CSS frameworks like Bootstrap or Tailwind include hundreds of rules for components not used on a given page, adding unnecessary download weight. Tools: PurgeCSS (removes unused rules based on HTML/JS analysis), UnCSS (similar, browser-based). For custom stylesheets, Chrome DevTools → Coverage panel shows which rules are actually used.
17. Remove unused JavaScript
Unused JavaScript not only wastes bandwidth — the browser must still parse and compile everything it downloads, adding execution time even for code that never runs. The Chrome DevTools Coverage panel (Ctrl+Shift+P → "Coverage") shows the percentage of each script file that is actually executed. Modules loaded by a bundler that are not tree-shaken are a common source of unused JS.
18. Reduce third-party scripts
Every third-party script tag — analytics, live chat, ad pixels, A/B testing tools, heat-mapping — adds a separate network request, a new DNS lookup, and JavaScript execution time that cannot be parallelised with your own code. Audit all active tags: list every third-party script in your tag manager, identify which are actively used, and remove the rest. The Page Speed Inspector's 3rd-Party Scripts tile gives you a count and lists the origins.
Measuring speed improvements
A checklist without measurement is just a to-do list. Run the Page Speed Inspector before starting to establish a baseline for each metric. After completing each tier of fixes, re-run and record the change. Key metrics to track and their targets:
| Metric | Good | Needs Improvement | Poor |
|---|---|---|---|
| TTFB | Under 800 ms | 800 ms – 1.8 s | Over 1.8 s |
| LCP | Under 2.5 s | 2.5 s – 4 s | Over 4 s |
| Total page weight | Under 1 MB | 1–3 MB | Over 3 MB |
| Render-blocking resources | 0 | 1–2 | 3+ |
TTFB is primarily a server and caching concern — if it is above 800 ms, start with fixes 5 and 6 (server-side caching and CDN) before optimising frontend resources. LCP is most affected by image optimisation (fixes 1–3), preloading (fix 8), and render-blocking elimination (fixes 7 and 10).
Each fix on this checklist targets a specific metric. Tracking the numbers before and after prevents the common trap of spending hours on fix 16 (unused CSS) when fix 4 (compression) would have delivered 10× the gain in a tenth of the time.
Measure Your Page Speed Baseline
Free, no signup. The Page Speed Inspector measures TTFB, LCP timing, render-blocking scripts, missing lazy loading, and DOM size — the specific metrics this checklist optimises for.
Try the Page Speed Inspector Free →Affiliate disclosure: Some links on this page may be affiliate links. We only mention tools we've personally used and have an honest opinion about. Affiliate revenue helps keep ByteWaveNetwork's tools free and maintained. We are not paid by any of the tools compared in this article for favorable coverage.