Every few weeks someone tells us their site is slow and asks whether they need a bigger server. Nine times out of ten, the server is fine. It renders the page in a few milliseconds and then waits patiently while the browser downloads megabytes of things nobody needed.
We recently audited a site — our own, as it happens — where the backend rendered the homepage in under 15 ms. It still felt sluggish. The culprit was a 3.5 MB stylesheet. Tailwind's unused-class purge had been switched off "temporarily" during development, and nobody switched it back on. Turning it on took the file down to 16 KB. No new hardware, one line of config.
Measure before you guess
Open Chrome DevTools, go to the Network tab, tick Disable cache, and reload. Sort by size. Whatever sits at the top of that list is your first job. Then run Lighthouse or PageSpeed Insights and look at two numbers:
- Largest Contentful Paint (LCP) — how long until the main content is visible. Aim for under 2.5 seconds.
- Interaction to Next Paint (INP) — how quickly the page responds when someone clicks or types. Aim for under 200 ms.
If the server's response time (TTFB) is small and those numbers are still bad, stop looking at the server.
The usual suspects
CSS that ships everything. Frameworks like Tailwind and Bootstrap are huge before you prune them. Make sure purging or tree-shaking runs in your production build, and check the output size in CI so it can't silently regress.
The same library loaded twice. It's surprisingly common to find jQuery, or a 3D library, included once from a CDN and again from a local file. Besides wasting bandwidth, the second copy can quietly overwrite the first and cause bugs that are miserable to track down.
Images straight from the camera. A 2 MB hero photo displayed at 600 pixels wide is just waste. Resize to the size you actually display, serve WebP or AVIF, add loading="lazy" to anything below the fold, and always set width and height so the layout doesn't jump.
Render-blocking scripts. Every <script> in the <head> without defer stops the page from drawing. Move scripts to the end of the body or mark them defer, and question whether each one is needed at all.
Slow work inside the request. For forms, the classic mistake is sending emails before responding. An SMTP handshake can take seconds. Hand the email to a background worker and respond straight away — the user doesn't need to wait for the mail server.
Make it stick
Performance decays quietly. A designer adds a font, a marketer adds a tag manager, a developer adds a carousel. None of them is wrong, but together they add up. Put a budget in place — for example, "no page over 1 MB, no CSS over 100 KB" — and check it in your pipeline. It's far easier to keep a site fast than to rescue a slow one.