Why your site is slow, and it is not the server
The first answer is almost always wrong
Someone says the site is slow. The next sentence is usually "the server is slow" or "we need a better hosting plan". I have been through that conversation many times and the server was the last thing to fix in nearly all of them. A page can take six seconds with a server that answers in 120 milliseconds, and I have measured that.
Measure first, and measure more than once
Open the page in a private window with the network panel open, do a hard reload, and write the numbers down: total time, number of requests, bytes transferred. Do it three times and look at the pattern rather than a single reading. If the page is fast on your machine and slow for the person complaining, the difference is in the conditions, not in the code: signed in or not, phone or desktop, cold cache or warm, one country or another.
Three numbers, not one
A page load is at least three different times stacked on top of each other.
- Time to first byte: from the request leaving the browser to the first byte of the response arriving. This is DNS, the connection, TLS, the web server and your application. It is the only part the server owns.
- Render time: from the first byte of HTML to the text being painted. This is parsing, CSS, render blocking scripts and layout.
- Asset time: everything after that. Images, fonts, analytics, chat widgets and anything else that loads late and keeps the main thread busy.
If time to first byte is 150 milliseconds and the total is five seconds, no server upgrade will help. If time to first byte is three seconds, the application is the problem and the rest is noise.
The waterfall shows you the shape
The network panel lists every request in the order it started, with bars showing when each one ran. Three shapes are worth recognising:
- A long block at the top with nothing else starting. Something is blocking, usually a stylesheet or a script in the head.
- A chain, where each request starts only after the previous one finishes. That is usually a request made from inside JavaScript that needed the previous response.
- A pile of requests at the bottom that nobody asked for. Trackers, widgets, fonts, a video player loading a poster frame.
Sort the list by size and then by duration. On most pages one image or one script accounts for a large share of the total, and finding it takes less time than reading about caching.
Only now the application
If time to first byte is the problem, then it is worth opening the slow query log and the profiler. The usual findings, in order of frequency: a query inside a loop that runs once per item in a list, a missing index on a column used in a where clause, a query with no limit that builds an array of everything. Caching one of those results is often worth more than any change to the hosting.
Fonts and other people's code
Fonts are a quiet cost. Every weight and every style is another file and another request, and a stylesheet that loads from a font service blocks rendering until it answers. Two weights, self hosted, is usually enough.
Third party scripts are the loud cost. A tag manager, an analytics snippet, a chat widget, an embedded map, a video. Each one is a new domain the browser has to connect to and JavaScript that competes for the main thread with your own. The metric that catches this is interaction to next paint: the target is 200 milliseconds or less at the 75th percentile, and one chat widget can eat most of it. The rest follows the same thresholds, LCP at 2.5 seconds and CLS at 0.1, all measured at the 75th percentile because that is the part of your traffic that hurts.
When the server really is the answer
There are real infrastructure problems. A box that runs out of memory and starts swapping. More concurrent workers than the memory can hold. A table with ten million rows and no index. A shared host that throttles at peak hours. Those are visible in the numbers: time to first byte climbs with traffic and drops when it falls, and it is bad for every page rather than one. When the numbers look like that, the server is the answer. Until then it is the most expensive guess available.
The order I use
- Measure three times and write the numbers down.
- Split the total into first byte, render and assets.
- Fix whichever part is biggest, then measure again.
- Change one thing at a time and keep the record.
- Talk about the server only when first byte is the biggest part.
What pays, in my experience, is images exported at print size, fonts loaded from three different domains, and a chat widget nobody uses. All of that is an afternoon of work and none of it involves a hosting plan.
Need a hand with a WordPress site that keeps breaking? See what I do and how I work.