Website Performance: 10 Measures That Work Immediately
Your website is slow? 10 performance measures you can implement today — from image optimization to Core Web Vitals. With before/after data.

Your website loads in 4.2 seconds. You know this because Google PageSpeed Insights just gave you a score of 38. Your competitor loads in 1.8 seconds. Their score is 92. And Google is now ranking them above you, even though your content is better.
The good news: most performance problems have straightforward fixes. You don't need to rebuild your entire site. In this article, I'll walk you through 10 concrete measures that deliver measurable improvements — many of them within a single afternoon.
Why performance matters (beyond PageSpeed scores)
Let's get the numbers out of the way first:
- A 1-second delay in load time reduces conversions by 7% (Akamai, 2024)
- 53% of mobile users leave a page that takes longer than 3 seconds to load (Google)
- Core Web Vitals are a confirmed ranking factor since 2021
- A fast site reduces bounce rate by 20-35% on average
Performance isn't a vanity metric. It directly impacts your revenue. If your site generates 100,000 EUR per year and a speed improvement increases conversions by 7%, that's 7,000 EUR more revenue from the same traffic. The optimisation work pays for itself within days.
The before/after impact table
Here's what each measure typically achieves. These numbers are based on real projects I've worked on — your results will vary depending on your starting point, but the relative impact is consistent.
| Measure | Effort | LCP Impact | PageSpeed Impact |
|---|---|---|---|
| Image optimisation (WebP/AVIF) | 1-2 hours | -0.5 to -2.0s | +10 to +25 points |
| Lazy loading | 30 min | -0.3 to -0.8s | +5 to +10 points |
| Font optimisation | 1 hour | -0.2 to -0.5s | +3 to +8 points |
| Bundle size reduction | 2-4 hours | -0.3 to -1.0s | +5 to +15 points |
| CDN setup | 1 hour | -0.2 to -0.8s | +3 to +10 points |
| Core Web Vitals fixes | 2-4 hours | -0.5 to -1.5s | +10 to +20 points |
| Caching headers | 30 min | -0.1 to -0.3s (repeat visits) | +2 to +5 points |
| Code splitting | 2-3 hours | -0.3 to -0.8s | +5 to +12 points |
| Server Components | 4-8 hours | -0.5 to -1.5s | +8 to +20 points |
| Database query optimisation | 2-6 hours | -0.2 to -1.0s | +3 to +10 points |
Combined, these measures can take a site from a PageSpeed score of 30-40 to 85-95. I've done this on my own site — you can read the case study here.
The 10 measures in detail
1. Image optimisation — the single biggest win
Images are responsible for 50-70% of page weight on most websites. And most of those images are served in formats and sizes that are wildly inefficient.
What to do:
- Convert all images to WebP (or AVIF for browsers that support it). WebP delivers 25-35% smaller files than JPEG at the same quality.
- Serve responsive images with
srcset— a 400px wide phone screen doesn't need a 2000px image. - Set explicit
widthandheightattributes to prevent layout shifts (CLS). - Use a tool like Sharp, Squoosh, or the built-in Next.js Image component for automatic optimisation.
In Next.js, the <Image> component handles most of this automatically. If you're on WordPress, install a plugin like ShortPixel or Imagify.
2. Lazy loading — only load what the user sees
By default, browsers load every resource on the page, even images and content far below the fold. Lazy loading defers the loading of off-screen content until the user scrolls to it.
What to do:
- Add
loading="lazy"to all images below the fold - Do NOT lazy-load the hero image or anything above the fold — that makes LCP worse
- Consider lazy-loading heavy components like maps, chat widgets, or embedded videos using
Intersection Observeror dynamic imports
One warning: lazy loading iframes (like YouTube embeds) can save massive amounts of data. A single YouTube embed loads 800KB+ of scripts. Use a facade pattern — show a thumbnail and only load the actual player when clicked.
3. Font optimisation — the invisible performance killer
Custom fonts are a sneaky performance drain. Each font file is 20-100KB, and most sites load 3-6 variants (regular, bold, italic, etc.). That's potentially 600KB of fonts blocking your page render.
What to do:
- Self-host your fonts instead of loading from Google Fonts. This eliminates an extra DNS lookup and connection.
- Use
font-display: swapso text is visible immediately with a system font, then swaps to the custom font when loaded. - Subset your fonts. If you only use Latin characters, strip the Cyrillic and Greek glyphs. This can reduce file size by 50-70%.
- Limit font variants. Do you really need thin, light, regular, medium, semibold, bold AND extra-bold? Usually 2-3 weights are enough.
Next.js has built-in font optimisation via next/font. It automatically self-hosts and subsets fonts. If you're not on Next.js, use google-webfonts-helper to download and self-host.
4. Bundle size reduction — ship less JavaScript
JavaScript is the most expensive resource on the web. Unlike images, JS must be downloaded, parsed, compiled AND executed. A 200KB JavaScript file takes more processing time than a 200KB image.
What to do:
- Run
npx next build(or your framework's equivalent) and check the bundle analysis. Find the largest chunks. - Replace heavy libraries with lighter alternatives: date-fns instead of moment.js (80% smaller), clsx instead of classnames.
- Check for tree-shaking issues:
import { debounce } from 'lodash-es'instead ofimport _ from 'lodash' - Remove unused dependencies. Run
npx depcheckto find packages you installed but never use.
I've seen sites drop their JavaScript from 1.2MB to 350KB just by replacing three libraries and removing dead code. That's a 70% reduction with maybe 3 hours of work.
5. CDN — serve content from the nearest edge
A CDN (Content Delivery Network) caches your static assets on servers worldwide. When a user in Munich loads your site, they get the files from Frankfurt instead of your origin server in Virginia.
What to do:
- If you're on Vercel, Netlify, orCloudflare Pages, you already have a CDN. Static assets are served from the edge by default.
- For traditional hosting, add Cloudflare (free tier is usually enough) as a reverse proxy in front of your site.
- Make sure your cache headers are correct — static assets should have long cache times (1 year) with content hashing for cache busting.
6. Core Web Vitals — fix what Google measures
Google measures three metrics: LCP (Largest Contentful Paint),INP (Interaction to Next Paint), and CLS (Cumulative Layout Shift). These directly affect your search rankings.
LCP (should be under 2.5s): Usually your hero image or headline. Optimise the image, preload it with <link rel="preload">, and make sure the server response is fast.
INP (should be under 200ms): Measures how quickly the page responds to user interactions. Reduce main thread blocking by splitting long tasks, using web workers for heavy computation, and debouncing event handlers.
CLS (should be under 0.1): Layout shifts happen when elements change size or position after the page loads. Fix by setting explicit dimensions on images and embeds, using font-display: optional if font swapping causes shifts, and reserving space for dynamic content.
7. Caching headers — don't re-download what hasn't changed
Proper caching means returning visitors load your site almost instantly. The browser serves files from its local cache instead of downloading them again.
What to do:
- Static assets (JS, CSS, images with hashes):
Cache-Control: public, max-age=31536000, immutable - HTML pages:
Cache-Control: public, max-age=0, must-revalidate(so you can deploy updates immediately) - API responses: Set
stale-while-revalidatefor data that doesn't change every second
8. Code splitting — load pages, not the entire app
Without code splitting, your entire application's JavaScript is bundled into one (or a few) large files. The user downloads code for every page even if they only visit the homepage.
What to do:
- Next.js and modern frameworks do route-based code splitting automatically. Each page only loads its own code.
- Use dynamic imports for heavy components:
const Chart = dynamic(() => import('./Chart')) - Split vendor code from application code so browser caching works better — your code changes often, React doesn't.
9. Server Components — less JavaScript to the client
If you're using React 18+ or Next.js 13+, Server Components are a game-changer. They render on the server and send HTML to the client — zero JavaScript for that component reaches the browser.
What to do:
- Default to Server Components. Only add
'use client'when you need interactivity (click handlers, state, effects). - Move data fetching into Server Components — no more loading spinners for initial data.
- Keep client components as small leaf nodes. The header and footer don't need to be client components just because they contain a mobile menu toggle.
On one of my projects, converting 60% of components from client to server reduced the client-side JavaScript by 45%. The LCP improved by 1.2 seconds.
10. Database query optimisation — the backend bottleneck
A beautiful, optimised frontend means nothing if the server takes 3 seconds to respond. Slow database queries are the most common backend performance problem.
What to do:
- Add indexes to columns you filter, sort, or join on. An unindexed query on 100,000 rows takes seconds; an indexed one takes milliseconds.
- Select only what you need.
SELECT *fetches every column. If you only need name and email, fetch name and email. - Avoid N+1 queries. If you're loading 20 products and then fetching the category for each one individually, that's 21 queries. Use a JOIN or batch fetch.
- Cache expensive queries. If a query takes 500ms and the data changes once per hour, cache it with a 5-minute TTL.
Tools for measuring performance
- Google PageSpeed Insights: Free, uses real user data (CrUX) for field metrics and Lighthouse for lab metrics.
- WebPageTest: More detailed than PageSpeed. Shows waterfall charts, filmstrip view, and lets you test from different locations.
- Chrome DevTools Performance tab: For deep-diving into specific issues like long tasks or layout shifts.
- Lighthouse CI: Automate performance testing in your CI/CD pipeline. Catch regressions before they reach production.
When to call a professional
Measures 1-7 are achievable for anyone with basic web knowledge. Install a plugin, tweak some settings, done. Measures 8-10 require development skills — code splitting, Server Components, and database optimisation involve actual code changes.
If your site scores below 50 on PageSpeed and you don't have a developer on staff, a professional website optimisation pays for itself fast. The typical project costs 2,000-5,000 EUR and delivers results within 1-2 weeks. Compare that to the revenue you're losing every day with a slow site.
Want a quick assessment of where your site stands? The free website audit analyses your performance, SEO, and conversion in one go.
FAQ: Website performance
What's a good PageSpeed score?
90+ is excellent, 50-89 needs improvement, below 50 is poor. For most business websites, aiming for 80+ on mobile is realistic and sufficient. Desktop scores are usually 10-20 points higher because desktop devices are faster.
Does performance really affect SEO?
Yes. Core Web Vitals are a confirmed ranking factor. But the impact is relative — great content with mediocre performance still beats mediocre content with perfect performance. Performance is a tiebreaker, not the main event.
How often should I check performance?
After every deployment that changes the frontend. Set up Lighthouse CI in your deployment pipeline to catch regressions automatically. At minimum, do a manual check once per month.
Can I improve performance without changing my tech stack?
Yes. Image optimisation, caching, font loading, and CDN setup work on any platform. WordPress, Shopify, custom PHP — the principles are the same. Only Server Components and advanced code splitting require a specific framework.
How much faster can my site realistically get?
That depends on your starting point. A WordPress site with unoptimised images, no caching, and 15 plugins can easily go from a 5-second load time to under 2 seconds. A modern Next.js site that's already decent might improve from 2.5 to 1.5 seconds. The worse your starting point, the bigger the gains from basic optimisations.
Related Articles
Need support?
I help you choose the right technology for your project — and build it.
Book a consultation