My Adobe Commerce performance checklist
Twelve checks, in order, that find most of the page-load time on a typical Adobe Commerce store before any code is written.
Every performance engagement starts the same way. Before I touch code, I run through the list below on a staging copy and against production monitoring. It usually explains most of the slowness, and it tells me where the first week of work should go.
The order matters. Infrastructure problems hide everything above them: if the full-page cache misses, no amount of frontend work will make category pages feel fast. So I start at the bottom of the stack and work up.
The thresholds below are my rules of thumb, not official numbers. They mark where I start asking questions, not hard limits.
Infrastructure
-
Full-page cache hit rate. Varnish or the built-in full-page cache. I look at the hit rate per page type, not one global number, because a healthy home page can hide a category page that misses on every request. If it is under 80% on category pages, fix that first. The usual causes are cookies or query parameters that vary the cache key, blocks that disable caching for the whole page, and cache tags that purge far more than they should after a product save.
-
Redis for sessions and cache. Sessions and cache belong in separate Redis instances, so a full cache cannot push out customer sessions. I check memory use, eviction counts and the eviction policy. Evictions on the session instance mean customers lose their carts; evictions on the cache instance mean the store keeps rebuilding the same data.
-
Search engine health. OpenSearch or Elasticsearch heap, shard count and the slow log. An undersized heap shows up as slow layered navigation and search results under load, long before it shows up as errors. I also check that the search index is not being rebuilt for the whole catalog several times a day.
-
PHP-FPM and OPcache. Enough workers for peak traffic, and not so many that the server starts swapping. OPcache must be large enough to hold the whole codebase, including generated code. When it fills up, PHP recompiles files on every request and response times jump without an obvious cause. I check
opcache.memory_consumption,opcache.max_accelerated_filesand the hit rate.
Backend
-
Indexers. Everything on “Update by Schedule”, cron running every minute, no indexers stuck in “processing” and no changelog tables growing without limit. “Update on Save” makes every admin save slower and can lock tables during busy hours. A stuck indexer also explains many cases of prices or stock that look wrong on the storefront.
-
Slow query log. I enable it on staging with production-sized data, or read it from database monitoring in production. Custom tables without indexes are the usual culprit, followed by collections loaded inside loops and custom attributes joined into every product listing. One missing index on a busy custom table can add seconds to a page.
-
Third-party modules on the hot path. Plugins and observers on product loading, price rendering, cart and checkout run on almost every request. I list them, disable each one in a staging copy and measure the difference. The result is usually a short list of two or three modules that cost most of the backend time, and a decision for each: configure, replace or remove.
-
Layout and block cache. A single block marked
cacheable="false"in a layout file makes the whole page uncacheable for the full-page cache. I search the codebase and every installed module for it. Personalized content belongs in private content sections loaded by JavaScript, not in uncacheable blocks.
Frontend
-
JavaScript payload. On a Luma-based theme I count the RequireJS modules loaded on a product page and look at how much script runs before the page becomes interactive. Bundling and minification help a little; removing modules nobody uses helps more. Hyvä stores avoid most of this problem, because the theme does not use RequireJS or the Luma JavaScript stack.
-
Critical CSS and font loading. One render-blocking stylesheet at most, critical CSS inlined for the first screen, and fonts loaded with
font-display: swapso text shows while the fonts arrive. I also count the font files and weights a page requests; a long list is a sign the design grew without anyone watching the cost. -
Images. Correct sizes for each breakpoint, WebP or AVIF, explicit width and height so the layout does not shift, and lazy loading below the fold. The main product image and the first row of category tiles should load eagerly, because lazy loading the largest image on the page delays Largest Contentful Paint.
-
Third-party tags. Analytics, chat, reviews, A/B testing and marketing pixels. Each tag manager container costs real milliseconds on the main thread. I list every tag, find out who owns it and whether anyone still uses its data. Load the rest after consent and after interaction where possible.
What the checklist gives you
At the end of the twelve checks I have a ranked list: what is broken, what it costs and what to fix first. Most stores have three or four items that matter and a long tail that does not. The ranked list becomes the plan for the fix phase, priced in hours so you can decide what is worth doing.
The checklist does not replace measurement. I record real-user data on the pages that carry revenue before and after every change, so the improvement shows up in numbers, not only in a feeling that the store is faster.
If you want this run on your store with a written report, see the performance optimization service.
Related posts
How I use AI coding agents on Adobe Commerce projects
Claude Code, hooks, skills and MCP on real Adobe Commerce work. What I hand to the agent, what I keep, and what changes for the merchant.
AIWhen to go headless on Adobe Commerce
Headless is a team and budget decision before it is a technology one. How I decide between Hyvä and a separate storefront on Adobe Commerce.
Headless