Measure first, never guess
Before you change anything, measure where the slowness lives. A feeling that "it feels sluggish" is not a diagnosis, and without measurement you often optimise the wrong part.
Split your measurement into two layers: the server (how quickly Magento returns the HTML) and the browser (how quickly the page becomes usable for the visitor). Google Core Web Vitals — LCP (load speed), CLS (visual stability) and INP (responsiveness) — measure that second layer and factor into your ranking.
- Server time: Time To First Byte per page type (home, category, product, checkout)
- Browser: LCP, CLS and INP from field data, not just a lab test
- Measure logged in and logged out — the full-page cache behaves differently for logged-in visitors than for anonymous ones
Hosting and cache configuration
The most common cause is not your code but your foundation. Magento 2 is heavy and runs poorly on shared hosting or an undersized VPS; it needs adequate CPU, memory and fast NVMe storage.
Just as important is that the caches are set up correctly. Varnish as full-page cache, Redis for sessions and objects, and a working OPcache make the difference between hundreds of milliseconds and several seconds. In practice we often find Varnish is not active, or the shop runs in developer mode on production — which recompiles on every request.
- Is the shop running in production mode, not developer mode?
- Is the full-page cache (Varnish) actually active and configured?
- Are Redis and OPcache enabled and not full or misconfigured?
Heavy theme and too much JavaScript
A classic Luma theme loads a lot of CSS and JavaScript, including RequireJS and jQuery, which block the browser before the page becomes usable. Every extra slider, pop-up and tracking pixel raises INP and worsens the experience on mobile.
A lightweight frontend such as Hyvä replaces that stack with minimal JavaScript and Tailwind CSS, significantly improving Core Web Vitals. Migrating is an investment, but it fixes a cause rather than a symptom.
Unoptimised images
Product photos are often the largest part of a page and therefore the direct cause of a slow LCP. Images loaded at full resolution while displayed small waste bandwidth and time.
Serve modern formats such as WebP or AVIF, scale images to their actual display size, and use lazy loading for everything below the fold. Explicitly reserve space for images to prevent layout shift (CLS).
Slow or poorly built modules
Every third-party module adds code that runs on each request. A single badly written extension — with uncached database queries, layout manipulation or external API calls in the critical path — can bring an otherwise healthy shop to its knees.
Use profiling to measure which plugins and observers cost time per module. Remove what you do not use, and assess the quality of every new extension before putting it on production. Fewer modules is almost always faster.
A maintained database and indexes
A Magento database grows under the hood: log tables, expired quotes, sessions and URL rewrites fill up over the years if nobody clears them. Large, bloated tables make every query slower.
Set indexers to "update on schedule" instead of on every save, keep the log-cleaning cron active, and prune historical data periodically. A healthy OpenSearch/Elasticsearch is also essential for fast category and search pages.