A slow website can be a 4 MB image.
It can also be the server taking two seconds to respond. A script from an analytics tool. A plugin doing far too much work. A database query that should take 20 milliseconds but takes a second and a half.
Or a bit of everything.
So when someone tells me their website is slow, my first question usually isn't what it's built in.
I measure it.
Otherwise you risk spending half a day optimising images on a website where the actual problem is somewhere else entirely.
What does "slow" actually mean?
That's the first thing to work out.
Is it the first page that takes a long time to appear? Does the page show up quickly but feel sluggish when you click something? Does the content jump around while it loads? Is it only the product pages? Only on mobile? Only for users who aren't logged in?
Or does the whole site just feel heavy?
Those symptoms can have very different causes.
A slow server can mean the browser is sitting there waiting before it has anything to show at all. A large image can mean the page starts quickly but takes a long time to get the important content in place. Too much JavaScript can mean everything looks downloaded while the browser is still busy working through it.
That's why "slow" isn't precise enough to start optimising against.
I start with the measurement
Lighthouse and PageSpeed Insights are often reasonable places to start.
But I use them as diagnostic tools, not as a verdict.
Among other things, I want to know how long the server takes to respond. Which files the browser fetches. How large they are. When the important content actually becomes visible. What's blocking the browser along the way. And what's happening for real users out there.
If the site has enough traffic, I prefer field data.
A lab test tells you what happened during one controlled run. Field data tells you what's actually happening on phones, computers and networks, out with real users.
The two don't always agree.
Images are still a classic
I still come across websites where an image is displayed at 600 pixels wide, but the browser is sent an original that's 4,000 pixels across.
That's rarely necessary.
Images need sensible dimensions, proper compression, and a format the browser can handle efficiently. And images further down the page usually don't need to be fetched before the user is close to them.
But image optimisation is also a good example of why you measure first.
If the images are already reasonably optimised, spending three hours squeezing another 30 KB out of them won't get you much.
There's no gain in thoroughly optimising the wrong problem.
JavaScript has a cost
The modern web can do an incredible amount.
Which also means we're sending an incredible amount of code down to the browser.
Analytics. Cookie consent. Chat. Tracking. Video. Ads. A/B tests. Form tools. Social media. Marketing automation.
Every single integration can be entirely legitimate on its own.
But the browser doesn't care about the org chart. It still has to fetch and run all of it.
So I'd often rather find out why a script is on the page than shave a few kilobytes off a CSS file. If nobody still knows why a third-party script is loading on every single page, that's worth looking into.
The fastest script is, after all, the one the browser never has to fetch.
Sometimes the problem is on the server
You can optimise the frontend as much as you like, but if the server takes a long time to assemble the page, you're already behind before anything is sent.
On a WordPress site, the cause might be plugins, heavy database queries, external API calls, or missing caching. On a custom-built solution, the problem might be a query pulling in far more data than necessary, or code doing the same work over and over. And sometimes the server is simply undersized or poorly configured.
Converting yet another image to WebP won't help much here.
You have to find the bottleneck.
Caching can make a huge difference
If a page is essentially the same for every visitor, there's rarely a good reason to rebuild it from scratch on every single visit.
That's the basic idea behind caching.
But caching exists in several layers. The browser can store files. A CDN can serve them closer to the user. The web server can cache whole pages or parts of them. The application can store results that would otherwise need recalculating. The database can avoid being asked the same question over and over.
That can make a very large difference.
But caching can also end up as a patch on a solution that's fundamentally doing too much work. If a database query takes three seconds, I want to know why – even if we cache the result afterwards.
Plugins aren't slow. Some plugins are.
On WordPress, the discussion quickly ends up at the number of plugins.
"We've got 37 plugins," the client will usually say. "Is that why the site is slow?"
Maybe.
But 37 doesn't tell me much on its own.
A small plugin might do one simple thing and barely register. Another might load scripts and styles on every page, make external calls, and run a handful of database queries on every visit.
So I want to know what those 37 plugins actually do before I start deleting them. The same goes for themes, frameworks and third-party solutions.
Mobile is often where reality shows up
A website can feel fast on the developer's MacBook with a fibre connection and still be slow for a large share of its users.
A phone doesn't necessarily have the same processing power. The connection isn't necessarily stable. And the browser might have plenty of other things going on at the same time.
"It loads fast for me," I hear now and then. That's not a particularly useful performance measurement.
It's also one of the reasons I prefer field data when there's enough of it. I'd rather know what users are actually experiencing than how fast the site is on my own computer.
Does everything need to be green?
No.
I like green numbers.
But I wouldn't spend hours moving a Lighthouse score from 98 to 100 if users already have a fast experience and that time could go somewhere more useful.
The same goes for Core Web Vitals. They're useful because they measure different parts of the user experience. But a website still has to work outside the measuring tool.
Lighthouse is a diagnosis, not a grade.
So what do you actually do about a slow website?
I wouldn't start by installing yet another performance plugin.
I'd start by finding out where the time is going.
If the server's response time is the problem, I look at the server, the application, the database and the caching. If it's the images, I work on size, format and delivery. If the browser is buried in JavaScript, I find out what's running, when it's running, and whether it needs to be there at all. If it's third-party scripts, sometimes you need to have the conversation about whether their value matches their cost. And if the problem only shows up on certain page types, that's where I start.
Measure first. Then optimise.
Performance work is obviously about technique. But a large part of it is about prioritisation. There will almost always be more you could optimise. The question is what actually makes a noticeable difference.
That's why I start with the measurement and work my way to the cause before I change anything. Otherwise you risk doing whatever's easiest to optimise, instead of whatever's actually making the website slow.
The fastest website isn't necessarily the one with the highest score. It's the one that feels fast to the people who actually have to use it.
Performance & SEOI work with performance from measurement and diagnosis to images, caching, database queries, JavaScript and technical SEO. The goal isn't 100 in Lighthouse. The goal is a fast website that works well for real users.
