Search for why your website is slow and you get the same list every time. Compress your images. Enable caching. Minify your CSS. Use a CDN.
All reasonable advice. None of it tells you which one is your problem. So people do all of it, spend two days, and the site is still slow — because the actual cause was a third-party chat widget loading 900KB of JavaScript before anything rendered.
Debugging is not a checklist. It is narrowing down. Here is a process that isolates the cause before you change anything.
Step 0: Measure the right page
Almost everyone tests their homepage. Almost nobody buys from the homepage.
Your traffic from Google lands on blog posts, product pages and category pages — built from different templates, usually carrying more images and more scripts than the carefully optimised homepage. Test the page that actually receives traffic and actually converts. A homepage scoring 95 while the product template sits at 48 is extremely common.
Step 1: Split the problem in two
Every slow page is slow for one of two reasons, and they have completely different fixes:
- The server is slow to respond — the browser asked for the page and waited.
- The server responded fast but the page takes ages to become usable — the HTML arrived quickly, then the browser spent four seconds downloading and executing things.
The metric that separates them is Time to First Byte (TTFB): how long between the request and the first byte of the response.
- TTFB under ~200ms — your server is fine. Skip to Step 3.
- TTFB over ~600ms — you have a backend problem. Step 2. Do not optimise images; they are not your issue.
You can read TTFB from your browser's Network tab, or from our free page speed test. This single number saves most people a day of work in the wrong direction.
Step 2: When the server is slow
High TTFB means the server is thinking too long before answering. Usual suspects, in order of how often they turn out to be the culprit:
Database queries
By far the most common cause on WordPress, WooCommerce and any custom app. Typically an N+1 problem: a page listing 50 products runs one query for the list, then one more query per product for its category, its price, its stock. That is 151 queries where three would do.
Enable your framework's query log on a staging copy and count the queries on the slow page. If the number is in the hundreds, you have found it.
No caching at all
If every request rebuilds the page from scratch, you are paying full cost for every visitor. Full-page caching turns a 900ms render into a 30ms file read. On WordPress this is a plugin and an afternoon.
Shared hosting under load
Sometimes the honest answer is the £3/month plan. If TTFB swings wildly between 200ms and 3s on identical requests, you are competing for CPU with other tenants. No amount of code optimisation fixes that.
A slow external API in the request path
Currency rates, stock levels, a reviews service. If your page waits on someone else's server before rendering, their bad day becomes your bad day. Cache the response or move the call to the browser.
Step 3: When the payload is the problem
Fast TTFB, slow page. Now look at what the browser downloads. Open DevTools, go to the Network tab, disable cache, reload, and sort by size.
Images — check this first, it is usually the answer
Look for anything over about 200KB. A single hero image exported straight from a phone or a design tool at 4000px wide, served unresized, is the most common cause of a slow page on the entire web.
Three fixes, in order of impact:
- Resize to the display size. If it renders at 800px, do not ship 4000px. This alone often cuts 90% of the weight.
- Convert to WebP or AVIF — typically 25–50% smaller than JPEG at equivalent quality.
- Lazy-load anything below the fold with
loading="lazy", but never on your main hero image — that delays the very thing you are trying to speed up.
JavaScript — check this second
Sort the Network tab by size and look at your JS bundles. Then ask a harder question about each one: do we still use this? Analytics from a campaign that ended, a chat widget nobody answers, an A/B testing script from a tool you cancelled. Third-party scripts accumulate because removing them is nobody's job.
Each one is a request, a download, a parse and an execution on the main thread — and on a mid-range Android phone, execution costs several times what it does on your laptop.
Web fonts
Four weights of two families is eight files before a single word appears. Use font-display: swap so text renders immediately in a fallback, and cut the weights you do not genuinely use.
Step 4: Find what is blocking the render
A page can be light and still feel slow if the browser is blocked from painting. By default, a <script> tag in the <head> stops HTML parsing until that script is downloaded and executed. Ten of them in sequence and nothing appears for two seconds on an otherwise fast page.
- Add
deferto scripts that do not need to run before render — which is nearly all of them. - Add
asyncto independent third-party tags like analytics. - Move non-critical CSS out of the blocking path.
This is often the single highest-leverage change on an otherwise well-built site.
Step 5: Read the Core Web Vitals as symptoms
Google's three metrics are useful as a diagnosis, because each points at a different cause:
- LCP (Largest Contentful Paint) is slow → your biggest visible element, usually the hero image, is arriving late. Go back to Step 3.
- CLS (Cumulative Layout Shift) is high → things are jumping around as they load. Almost always images or ad slots without reserved width and height, or a web font swapping at a different size.
- INP (Interaction to Next Paint) is poor → the main thread is busy. Too much JavaScript executing. Step 3 again, JS section.
Our Core Web Vitals test reports all three, and this guide covers what each one means in more depth.
Step 6: Check whether it is only slow for some people
If the site is fast for you and slow for customers, you are testing under the wrong conditions:
- Geography. A server in Mumbai serving customers in Texas adds latency on every request. That is what a CDN solves.
- Device. Throttle to "Mid-tier mobile" in DevTools. A JS-heavy page that feels instant on a MacBook can take six seconds on a three-year-old Android.
- Cache state. You have everything cached. A first-time visitor does not. Always test with cache disabled.
The short version
- Test the page that gets traffic, not the homepage.
- Read TTFB. High means backend, low means payload. This one number decides everything after it.
- Backend: count your database queries, then check caching.
- Payload: sort by size. It is nearly always an oversized image or a forgotten third-party script.
- Add
deferto scripts in the head. - Retest on a throttled mobile connection with cache disabled.
You can shortcut most of Steps 1 to 5 with a full site audit — it reports TTFB, compression, caching headers, oversized images, render-blocking scripts and Core Web Vitals across every page, so you see whether the problem is one page or the template behind four hundred of them.
For the specific fixes once you know the cause, see how to improve website speed.