A slow website is rarely slow for one reason. It is usually a stack of small problems: heavy images, unused JavaScript, slow database queries, and no caching. Here is how we find the bottlenecks and the order we fix them in.
The problem
If a page takes more than two or three seconds to become useful, people leave. Search engines measure Core Web Vitals: LCP (when the main content appears), INP (how quickly the page responds to input), and CLS (how much the layout jumps). Poor numbers cost you both leads and rankings.
Why it happens
- The server is slow to respond. A TTFB above 600 ms points to slow PHP or Node.js, heavy database queries, or no page cache.
- Images are too heavy. 2–5 MB photos without responsive sizes or modern formats.
- Too much JavaScript. Sliders, widgets, trackers, and plugins loaded on every page whether they are needed or not.
- Render-blocking fonts and CSS. The browser waits for them before it shows any text.
- No CDN. Static files travel halfway around the world to reach the visitor.
How we find the bottlenecks
- Lighthouse and PageSpeed Insights for a first look. We ignore the overall score and read the individual metrics and the loading waterfall.
- Chrome DevTools → Performance to see where the time goes: network, script parsing, or rendering.
- Server logs and profiling: slow SQL queries, page generation time, CPU load.
- Real-user data (CrUX, RUM), because a lab test on a fast laptop says nothing about a phone on 4G.
What we fix first
| Problem | Fix | What improves |
|---|---|---|
| Slow TTFB | Page cache, OPcache, Redis, query tuning | Server response time |
| Heavy images | WebP or AVIF, srcset, lazy loading |
LCP and bandwidth |
| Unused JS | Remove dead plugins, load scripts on demand | INP |
| Layout shifts | Fixed dimensions for media and blocks | CLS |
| Distant server | A CDN such as Cloudflare | Static asset delivery |
Technical details
On WordPress the usual combination is a plugin audit, an object cache, full-page caching in Nginx, and moving heavy work such as imports and email sending into background jobs. On React and Next.js it is server rendering or static generation, bundle splitting, and fewer client-side requests where the data can ship in the HTML.
Long-lived caching for static files in Nginx:
location ~* \.(webp|avif|jpg|png|svg|woff2)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
Example
A typical case is a WooCommerce store whose homepage takes 6–7 seconds on mobile. Under the hood there are 40 active plugins, a slider with five full-size photos, and a separate database query for every product in the catalog. The order of work: disable the plugins the store can live without, convert images to WebP with responsive sizes, enable page caching, and batch the catalog queries. On projects like this, LCP usually comes down to 2–2.5 seconds.
Takeaway
Speeding up a site is not "install a caching plugin". It is finding the specific bottlenecks and removing them one by one. Measure first, then fix the server, images, and JavaScript — in that order you usually get the biggest gain.