TL;DR — Quick Summary
Magento stores are slow because of misconfigured Varnish FPC (cache hit rates below 85%), extension bloat (each extension adds database queries, JavaScript, and event observers), untuned Redis/MySQL, and heavy front-end frameworks (RequireJS + KnockoutJS on Luma theme). Quick wins: 1) Verify Varnish FPC is working — check X-Cache headers and aim for 90%+ hit rates. 2) Audit extensions — disable one at a time, measure TTFB difference, remove unused ones (disabled extensions still load config). 3) Configure Redis with separate databases for cache (db0, allkeys-lru) and sessions (db1, noeviction), using Unix sockets. 4) Optimize MySQL — add missing indexes, clean orphaned data, tune innodb_buffer_pool_size to 70% of available RAM. 5) Migrate to Hyvä theme to replace RequireJS/KnockoutJS with Alpine.js (80%+ JS reduction). 6) Preload LCP images, inline critical CSS, defer non-critical JS. 7) Reserve CSS min-height for ESI blocks to prevent CLS. 8) Monitor CrUX field data — Google uses the 75th percentile of real-user data over 28 days for ranking, not lab scores.
Key Takeaways
- ✓Magento's layered architecture (Varnish → Redis → PHP-FPM → MySQL → Elasticsearch) means performance issues can originate at any layer — and each layer has dedicated optimization levers.
- ✓Varnish FPC misconfiguration is the #1 cause of slow Magento stores — properly configured, it reduces TTFB from 2–5 seconds to under 100ms.
- ✓Extension bloat compounds exponentially: each extension adds database queries, JavaScript, CSS, event observers, and plugins that intercept core logic.
- ✓The Hyvä theme replaces RequireJS and KnockoutJS with Alpine.js, reducing front-end JavaScript by 80%+ and eliminating most INP issues.
- ✓Redis must be configured with separate databases for cache vs. sessions, proper eviction policies, and Unix sockets for lowest latency.
- ✓Elasticsearch/OpenSearch tuning dramatically improves category and search page performance — the most visited page types on e-commerce sites.
- ✓A properly optimized Magento store can achieve sub-100ms TTFB (cached), 90+ Lighthouse scores, and outperform simpler platforms.
Magento's Performance Architecture: Understanding the Stack
Magento (Adobe Commerce) is the most architecturally complex e-commerce platform available. Understanding its layered architecture is essential before optimizing — because performance issues can originate at any layer, and fixing the wrong layer wastes time.
The request lifecycle flows through six distinct layers:
- 1CDN/Edge Layer: Fastly (Adobe Commerce Cloud) or your chosen CDN handles static assets, SSL termination, and potentially edge-side logic
- 2Varnish HTTP Cache: Serves cached HTML pages directly, bypassing PHP entirely for cache hits — this is where the biggest TTFB wins happen
- 3Web Server (Nginx/Apache): Routes requests to PHP-FPM, serves static files, handles SSL if not terminated at CDN
- 4PHP-FPM Application: Executes Magento's PHP code — routing, business logic, template rendering, event dispatch
- 5Data Layer: MySQL/MariaDB for persistent data, Redis for object cache and sessions, Elasticsearch/OpenSearch for search and catalog navigation
- 6Front-End Layer: Browser rendering of HTML/CSS/JavaScript — RequireJS + KnockoutJS (Luma) or Alpine.js + Tailwind (Hyvä)
The critical insight: optimizing layer 6 (front-end) while layer 2 (Varnish) is misconfigured is like polishing a car with a broken engine. Always optimize from the bottom up: infrastructure first, then application, then front-end.
For Adobe Commerce Cloud specifically, Fastly acts as both CDN and Varnish replacement — its VCL snippets control caching behavior, and its Image Optimizer handles responsive image delivery. Understanding whether you're on self-hosted (you manage Varnish) or Cloud (Fastly manages caching) determines which tools and configurations apply.
Varnish Full Page Cache: The Single Biggest Performance Lever
Varnish FPC is the most impactful optimization for any Magento store. When properly configured, it reduces TTFB from 2–5 seconds (PHP execution) to under 100ms (served from memory). No other single change comes close to this impact.
How Varnish Works with Magento
Varnish sits in front of your web server and caches complete HTML responses. When a visitor requests a page, Varnish checks if it has a cached copy. If yes (cache hit), it serves the HTML directly from RAM — PHP never executes. If no (cache miss), the request passes through to Magento, and Varnish stores the response for future requests.
VCL Configuration
Magento generates a base VCL file (bin/magento varnish:vcl:generate), but you'll need to customize it:
- •Vary headers: Pages vary by currency, language, customer group, and store view. Incorrect Vary configuration causes either cache pollution (wrong content served) or cache fragmentation (too many variants, low hit rate)
- •TTL settings: Static pages (CMS, about) → 86400s; category pages → 3600s; PDPs → 1800s; cart/checkout → 0 (never cache)
- •Grace mode: Serve stale content for 300–600s while the backend regenerates — prevents thundering herd on cache expiry
- •Health checks: Configure backend probes so Varnish serves stale content if PHP-FPM is overloaded rather than returning 503 errors
ESI (Edge Side Includes) Hole-Punching
Magento uses ESI to handle dynamic blocks within cached pages. The page HTML is cached, but blocks like cart count, customer greeting, and recently viewed products are fetched separately via ESI tags. Common issues:
- •Too many ESI blocks reduce the benefit of FPC (each is a separate backend request)
- •ESI blocks with slow rendering increase overall page TTFB
- •Missing ESI configuration causes entire pages to be marked uncacheable
Debugging Cache Misses
Use varnishlog to trace why requests miss cache:
- •Check for cookies preventing caching (especially third-party analytics cookies)
- •Look for Vary header mismatches
- •Identify URLs with query parameters that fragment cache
- •Monitor X-Magento-Cache-Debug header (HIT/MISS) in browser DevTools
Cache Warming
After deployment (bin/magento cache:flush clears Varnish), run a cache warming script that crawls your sitemap URLs. This ensures no real visitor hits an uncached page. Use wget or a custom script with concurrency limits (don't overwhelm the backend):
wget --spider --recursive --no-parent --quiet --header="X-Magento-Cache-Warm: 1" https://yourstore.com/sitemap.xml
Redis Configuration: Object Cache, Sessions, and Tuning
Redis serves two critical roles in Magento: object caching (storing compiled configuration, layout XML, and block HTML) and session storage (keeping user sessions in-memory instead of files or database).
Separate Databases for Cache vs. Sessions
Never use the same Redis database for both — they have fundamentally different requirements:
- •Cache (db0): Use allkeys-lru eviction. When memory fills, Redis evicts least-recently-used keys. This is safe because cached data can be regenerated.
- •Sessions (db1): Use noeviction policy. Sessions must never be evicted during a user's checkout flow — evicting a session mid-purchase causes cart abandonment.
Memory Configuration
Set maxmemory based on your catalog size and traffic:
- •Small stores (< 10K SKUs): 256MB cache, 128MB sessions
- •Medium stores (10K–100K SKUs): 512MB cache, 256MB sessions
- •Large stores (100K+ SKUs): 1GB+ cache, 512MB sessions
Monitor with redis-cli INFO memory — if used_memory_peak approaches maxmemory, increase allocation.
Connection Optimization
For same-server deployments, use Unix sockets instead of TCP:
'session' => ['save' => 'redis', 'redis' => ['host' => '/var/run/redis/redis.sock', 'port' => '0', 'database' => '1']]
Unix sockets eliminate TCP overhead (handshake, packet framing), saving 10–20% latency per operation. For remote Redis (ElastiCache, Redis Cloud), ensure the Redis instance is in the same availability zone as your web servers.
Monitoring Key Metrics
- •hit_rate: cache_hits / (cache_hits + cache_misses) — target 95%+
- •evicted_keys: Should be near zero for sessions, acceptable for cache if hit rate stays high
- •connected_clients: Watch for connection leaks from misconfigured PHP-FPM workers
- •instantaneous_ops_per_sec: Baseline for capacity planning
PHP-FPM and OPcache: Application Layer Performance
PHP-FPM (FastCGI Process Manager) manages the pool of PHP workers that execute Magento's application code. Misconfiguration here causes either wasted resources (too many idle workers) or request queuing (too few workers during traffic spikes).
Worker Count Formula
Each Magento PHP-FPM worker consumes 128–256MB of RAM. Calculate max_children:
(available_RAM_MB × 0.7) / average_worker_memory_MB = max_children
Example: 16GB server → (16384 × 0.7) / 200 = ~57 workers
Set pm = dynamic with:
- •pm.start_servers = 25% of max_children
- •pm.min_spare_servers = 10% of max_children
- •pm.max_spare_servers = 75% of max_children
- •pm.max_requests = 1000 (recycle workers to prevent memory leaks)
OPcache Configuration
OPcache caches compiled PHP bytecode, eliminating the need to parse and compile PHP files on every request. Magento has thousands of PHP files, making OPcache essential:
opcache.memory_consumption=256 opcache.max_accelerated_files=65536 opcache.validate_timestamps=0 (production only — clear manually on deploy) opcache.interned_strings_buffer=32 opcache.save_comments=1 (required by Magento's annotation-based DI)
Verify with opcache_get_status(): hit rate should be 99%+, and num_cached_files should match the total number of PHP files in your Magento installation.
PHP 8.1+ JIT Compilation
Enable the JIT compiler for additional 10–25% execution speed on computation-heavy operations (price rules, EAV loading, indexing):
opcache.jit_buffer_size=128M opcache.jit=1255 (tracing mode)
Monitor with opcache_get_status()['jit'] — look for increasing opt_level counts indicating hot code paths are being JIT-compiled.
Extension Audit: Identifying and Eliminating Bloat
Magento's extension marketplace is both its greatest strength and its biggest performance weakness. Each installed extension potentially adds:
- •Database tables and queries: Some extensions add 10+ tables and run queries on every page load
- •Event observers and plugins: Intercept core logic at potentially hundreds of interception points — each adding microseconds that compound into milliseconds
- •Front-end assets: JavaScript, CSS, and templates loaded on every page regardless of whether the extension's functionality is needed on that page
- •Admin panel overhead: Configuration loading, menu rendering, and system checks that slow admin operations
- •Cron jobs: Background processes competing for server resources
The Profiling Process
- 1List all installed extensions: bin/magento module:status
- 2Baseline performance: measure TTFB on homepage, a category page, and a PDP
- 3Disable extensions one at a time: bin/magento module:disable Vendor_Module
- 4Re-measure TTFB after each disable
- 5Create a spreadsheet: extension name, TTFB impact, business value, verdict (keep/remove/replace)
Critical Insight: Disabled Extensions Still Load Config
Simply disabling an extension via the admin panel doesn't remove its performance overhead. The module's etc/ configuration XML is still loaded and parsed on every request. To fully eliminate an extension's impact, you must remove it via Composer: composer remove vendor/module-name
Plugin Chain Analysis
Use bin/magento dev:di:info to trace which extensions intercept which methods. Look for extensions that plugin into hot code paths:
- •Catalog product load (called hundreds of times on category pages)
- •Quote/cart operations (called on every page with mini-cart)
- •Customer session initialization (called on every authenticated request)
Target: Under 30 Active Third-Party Extensions
Stores with 50+ extensions almost always have severe performance issues. For every extension, ask: Is this functionality available in Magento core? Can it be replaced with a lighter alternative? Is the business value worth the performance cost?
Struggling with Magento speed?
Our team optimizes Magento sites for real-world results. Request an audit.
MySQL/MariaDB Optimization: Queries, Indexes, and Configuration
Magento's EAV (Entity-Attribute-Value) data model creates complex queries with multiple JOINs across attribute tables. This architecture provides flexibility (unlimited custom attributes) at the cost of query performance.
Slow Query Analysis
Enable the slow query log:
slow_query_log = 1 long_query_time = 1 slow_query_log_file = /var/log/mysql/slow.log
Analyze with mysqldumpslow or pt-query-digest (Percona Toolkit). Common slow query patterns in Magento:
- •EAV attribute loading: Product loads joining 10+ attribute tables — fix with flat catalog indexes or targeted attribute selection
- •Category product counts: Full table scans for layered navigation — fix with proper anchored category indexing
- •Quote item collection: Cart queries joining multiple tables — fix by cleaning abandoned quotes (bin/magento cron:run --group=sales_clean_quotes)
- •Search queries: Full-text searches falling back to MySQL instead of Elasticsearch — fix by ensuring Elasticsearch is properly configured as the search engine
Key InnoDB Settings
innodb_buffer_pool_size = 70% of available RAM (the most impactful MySQL setting) innodb_log_file_size = 256MB–1GB (larger = better write performance, slower recovery) innodb_flush_method = O_DIRECT (avoid double-buffering with OS page cache) table_open_cache = 4000 (Magento has hundreds of tables) max_connections = 150 (match PHP-FPM worker count + cron + admin)
Data Hygiene
Magento accumulates data that bloats tables and slows queries:
- •Clean expired quotes: DELETE FROM quote WHERE updated_at < DATE_SUB(NOW(), INTERVAL 30 DAY) AND is_active = 1
- •Remove orphaned catalog images: bin/magento catalog:images:remove-orphans
- •Clean old log entries: bin/magento log:clean
- •Rebuild flat catalog indexes: bin/magento indexer:reindex catalog_product_flat catalog_category_flat
Indexer Configuration
Set all indexers to 'Update by Schedule' (not 'Update on Save'). 'Update on Save' triggers reindexing on every product save, causing write amplification during bulk imports and admin operations. 'Update by Schedule' batches changes and processes them via cron, typically every minute.
Elasticsearch/OpenSearch: Catalog Search and Navigation
Elasticsearch (or OpenSearch in Adobe Commerce 2.4.6+) powers category pages, search results, and layered navigation — collectively the most visited page types on e-commerce sites. Proper tuning here impacts the majority of your traffic.
Index Configuration
- •number_of_replicas: Set to 1 for read performance (queries can be served by either primary or replica shard)
- •refresh_interval: Change from default 1s to 30s for better indexing throughput. Products don't need to be searchable within 1 second of saving.
- •max_result_window: Set appropriate for your catalog size (default 10000 is fine for most stores)
- •Translog durability: Set to 'async' with sync_interval of 5s for better write performance during reindexing
Analyzer Configuration
Magento's default analyzers work for basic search but can be improved:
- •Autocomplete: Add edge_ngram tokenizer for instant search suggestions
- •Synonyms: Configure synonym filters for common product term variations (e.g., 'couch' → 'sofa', 'TV' → 'television')
- •Stop words: Customize stop word lists for your product domain
Query Performance
Monitor individual query latency with /_nodes/stats — queries should complete in under 50ms. If category pages are slow:
- •Check that layered navigation attributes are mapped as keyword type (not analyzed text)
- •Ensure aggregation queries use the terms aggregation (not scripts)
- •Verify that product visibility and status filters use filter context (cached) not query context
Large Catalog Optimization (100K+ SKUs)
For very large catalogs:
- •Increase Java heap size (ES_JAVA_OPTS) to 50% of server RAM, max 32GB
- •Consider separate indexes for search vs. category navigation
- •Use scroll API for bulk operations instead of deep pagination
- •Monitor JVM garbage collection — long GC pauses cause search latency spikes
Front-End Optimization: Luma vs. Hyvä Theme Performance
Magento's front-end is where the most dramatic performance differences exist between stores. The choice between Luma (default) and Hyvä (modern alternative) is the single biggest front-end decision you'll make.
Luma Theme: The Legacy Stack
Luma ships with Magento and uses:
- •RequireJS: AMD module loader that manages JavaScript dependencies. The problem: it loads modules synchronously, creating waterfall chains where each module must load before its dependents can initialize.
- •KnockoutJS: MVVM framework used for dynamic UI (mini-cart, checkout, configurable product options). The problem: KnockoutJS templates are compiled in the browser, creating long tasks during page initialization.
- •jQuery + jQuery UI: Used extensively throughout Luma, adding 90KB+ of JavaScript overhead.
- •Less CSS: Compiled server-side, but the generated CSS includes substantial unused rules.
Total front-end JavaScript on a typical Luma PDP: 300–500KB (compressed), executing 1–3 seconds of main-thread work.
Hyvä Theme: The Modern Stack
Hyvä replaces the entire Luma front-end stack with:
- •Alpine.js: 15KB reactive framework (vs. KnockoutJS's 60KB+). Components initialize instantly with minimal main-thread impact.
- •Tailwind CSS: Utility-first CSS that generates only the classes you use — typical Hyvä CSS: 20–40KB vs. Luma's 200KB+.
- •No RequireJS: Scripts use standard ES modules with dynamic import() for code splitting.
- •No jQuery: Native JavaScript APIs replace jQuery utilities.
Total front-end JavaScript on a typical Hyvä PDP: 40–80KB (compressed), executing under 200ms of main-thread work.
Migration Considerations
Hyvä migration timeline: 2–8 weeks depending on customization complexity. Key factors:
- •Custom Luma templates must be rewritten for Alpine.js
- •Third-party extensions need Hyvä-compatible versions (the Hyvä compatibility module handles many automatically)
- •Checkout customizations are the most complex to migrate
- •The Hyvä ecosystem has grown rapidly — 90%+ of common extensions now have Hyvä versions
Optimizing Luma (If Migration Isn't Feasible)
If you must stay on Luma:
- 1Advanced JS bundling: bin/magento setup:static-content:deploy with --strategy=compact. Configure requirejs-config.js to bundle related modules.
- 2Critical CSS: Use tools like Penthouse to extract and inline above-fold CSS, deferring the rest.
- 3Lazy KnockoutJS init: Wrap KnockoutJS component initialization in IntersectionObserver callbacks — only initialize components when they scroll into view.
- 4Remove jQuery UI: Most Luma stores only use a fraction of jQuery UI widgets. Create a custom build that includes only what you need.
- 5Preload key modules: Use
<link rel="modulepreload">for critical RequireJS modules to eliminate waterfall chains.
Image Pipeline: WebP, AVIF, and Responsive Delivery
Images typically account for 60–80% of page weight on Magento product pages. An optimized image pipeline can cut total page weight by 50%+ without any visible quality loss.
Format Selection
- •WebP: 25–35% smaller than JPEG at equivalent quality. Supported by 97%+ of browsers. This should be your default format.
- •AVIF: 40–50% smaller than JPEG, but encoding is slower and browser support is 93%. Use as progressive enhancement with
<picture>element fallback. - •JPEG: Fallback format for the 3% of browsers without WebP support.
- •SVG: For logos, icons, and illustrations — infinitely scalable, typically 1–5KB.
Magento Image Configuration
Configure image resizing in view.xml:
<image id="category_page_grid" type="small_image"><width>240</width><height>300</height></image>
<image id="product_page_image_medium" type="image"><width>700</width><height>700</height></image>
Generate responsive srcsets:
<img srcset="product-240w.webp 240w, product-480w.webp 480w, product-700w.webp 700w" sizes="(max-width: 640px) 240px, (max-width: 1024px) 480px, 700px" src="product-700w.jpg" alt="Product Name" width="700" height="700" loading="lazy">
LCP Image Preloading
The hero image on each page type must be preloaded — it's almost always the LCP element:
<link rel="preload" as="image" type="image/webp" href="hero-banner.webp" fetchpriority="high">
Add this in the <head> of your layout XML for homepage, category, and landing page templates. Do NOT preload images on PDPs — the main product image is typically below fold on mobile.
Adobe Commerce Cloud: Fastly Image Optimizer
If on Adobe Commerce Cloud, enable Fastly IO for automatic format conversion, resizing, and quality optimization at the CDN edge — no Magento-side image processing needed. Configure in Stores → Configuration → Advanced → System → Full Page Cache → Fastly → Image Optimization.
Core Web Vitals: Passing All Three Metrics on Magento
Magento stores face unique Core Web Vitals challenges compared to other platforms. The combination of server-side complexity (TTFB), heavy front-end frameworks (INP), and dynamic content injection (CLS) creates a trifecta of CWV issues that requires a holistic approach.
LCP (Largest Contentful Paint) — Target: < 2.5s
LCP on Magento is primarily a TTFB problem. Fix the server stack first (Varnish, Redis, PHP-FPM), then optimize the client side:
- •Verify Varnish FPC is serving cached responses (X-Cache: HIT header)
- •Preload the LCP image (hero banner on homepage, first product image on category pages)
- •Inline critical CSS — the CSS needed to render above-fold content should be in the
<head>, not a separate file - •Defer non-critical JavaScript — RequireJS bundles that aren't needed for initial render should load after LCP
- •Use fetchpriority="high" on the LCP image element
- •Ensure CDN is serving images from edge locations close to your users
INP (Interaction to Next Paint) — Target: < 200ms
INP measures the responsiveness of interactions (clicks, taps, key presses). Magento's biggest INP challenges:
- •RequireJS module initialization: On Luma, clicking an element that requires a not-yet-loaded module triggers a synchronous load chain. Fix: preload critical interaction modules or migrate to Hyvä.
- •KnockoutJS template rendering: Configurable product options (size, color selectors) trigger KnockoutJS re-rendering that blocks the main thread. Fix: break updates into smaller batches with requestAnimationFrame.
- •Add-to-cart handlers: The full add-to-cart flow (validation, AJAX request, mini-cart update, message display) is a single synchronous operation. Fix: respond immediately with UI feedback, process the rest asynchronously.
- •Mega menu interactions: Nested navigation menus with hundreds of items. Fix: render submenus on hover/click, not on page load.
CLS (Cumulative Layout Shift) — Target: < 0.1
CLS on Magento is primarily caused by:
- •ESI blocks: Varnish hole-punched blocks (cart count, customer greeting, recently viewed) render after the initial cached HTML, pushing content down. Fix: reserve space with CSS min-height on ESI container elements.
- •Late-loading product images: Images without explicit dimensions cause layout shifts when they load. Fix: add width and height attributes to all
<img>tags in templates. - •Web fonts: Font swap causes text to reflow. Fix: use font-display:swap with size-adjusted fallback fonts (@font-face with size-adjust, ascent-override, descent-override).
- •Dynamic content injection: Reviews, related products, and upsell blocks loaded via AJAX. Fix: reserve skeleton placeholders with min-height.
Testing Strategy
Test the four critical page types separately — they have very different performance profiles:
- 1Homepage (usually passes easiest — mostly static content)
- 2Category/listing pages (hardest for INP — layered navigation interactions)
- 3Product detail pages (hardest for LCP — hero image + heavy JS initialization)
- 4Checkout (hardest overall — heavy JS application with complex interactions)
Use CrUX Dashboard to monitor field data by page type, not just origin-level metrics.
Adobe Commerce Cloud: Platform-Specific Optimization
Adobe Commerce Cloud (formerly Magento Commerce Cloud) runs on a managed infrastructure with Fastly CDN, AWS services, and automated deployment pipelines. While you lose some configuration control compared to self-hosted, Cloud offers platform-specific optimizations:
Fastly Configuration
Fastly replaces Varnish on Cloud. Configure via Stores → Configuration → Advanced → System → Full Page Cache → Fastly:
- •VCL snippets: Custom Varnish logic deployed via Fastly's API — no direct VCL file editing
- •Shielding: Enable a shield POP to reduce origin requests. All edge POPs send cache misses to the shield first, which checks its cache before hitting origin.
- •Soft purging: Use surrogate keys for targeted cache invalidation instead of full purges
- •Image Optimizer (IO): Automatic WebP/AVIF conversion, responsive resizing, and quality optimization at the edge
Environment Sizing
Cloud environments are sized by CPU and RAM. For performance:
- •Production: Minimum M4 (4 vCPU, 16GB RAM) for stores with 50K+ SKUs
- •Use dedicated worker tier for cron jobs and indexing — don't compete with web traffic
- •Scale horizontally (more web instances) for traffic spikes, not vertically
Deployment Optimization
Cloud deployments clear all caches. Optimize the post-deploy phase:
- •Static content deployment: Use --strategy=compact --jobs=4 to parallelize
- •Cache warming: Add post_deploy hook to warm critical URLs
- •Zero-downtime deployment: Ensure health checks pass before routing traffic to new instances
New Relic Integration
Cloud includes New Relic APM. Use it to:
- •Monitor transaction response times by page type
- •Identify slow database queries with Query Analysis
- •Track deployment performance impact with Deployment Markers
- •Set up alerts for TTFB exceeding thresholds
Thresholds & Benchmarks
| Metric | Good | Needs Improvement | Poor |
|---|---|---|---|
| TTFB (cached via Varnish) | < 100ms | 100–500ms | > 500ms |
| TTFB (uncached) | < 400ms | 400–1200ms | > 1200ms |
| LCP (mobile) | < 2.5s | 2.5–4.0s | > 4.0s |
| INP | < 200ms | 200–500ms | > 500ms |
| CLS | < 0.1 | 0.1–0.25 | > 0.25 |
| Varnish cache hit rate | > 90% | 85–90% | < 85% |
| Redis memory utilization | < 70% | 70–90% | > 90% |
| Total page weight (mobile) | < 1.5MB | 1.5–3MB | > 3MB |
Key Measurement Tools
Combines Lighthouse lab audit with CrUX field data. The primary tool for checking Core Web Vitals on Magento — test homepage, category pages, PDPs, and checkout separately.
Real-user performance data from Chrome users. Google's actual ranking signal — check that your 75th percentile values pass thresholds across all page types.
Server-side application performance monitoring. Essential for Magento — tracks PHP execution time, database query duration, Redis hit rates, and identifies slow code paths per request.
Varnish's built-in monitoring tools. Varnishstat shows cache hit rates and memory usage; varnishlog traces individual requests through VCL rules to debug cache misses.
Monitor Redis memory usage, hit/miss ratios, eviction counts, and connected clients. Essential for tuning memory limits and eviction policies.
Analyze query execution plans and identify slow queries. Enable slow_query_log with long_query_time=1 to catch queries taking over 1 second.
Built-in profiler that traces block rendering, template loading, and observer execution. Enable in app/etc/env.php to identify which modules consume the most rendering time.
Detailed waterfall analysis with filmstrip view. Test from multiple locations to verify CDN effectiveness and Varnish behavior for different geographic regions.
Looking for speed help?
Step-by-Step Optimization Guide
Audit and Configure Varnish Full Page Cache
Varnish FPC is the single most impactful optimization for Magento. Verify it's active by checking X-Cache and X-Magento-Cache-Control response headers. Review your VCL (Varnish Configuration Language) rules: ensure correct handling of currency/language/customer-group variations via Vary headers, configure ESI (Edge Side Includes) hole-punching for dynamic blocks (cart count, customer greeting, recently viewed), set appropriate TTLs (86400s for static pages, 3600s for category pages, 1800s for PDPs), and implement proper health checks so Varnish serves stale content gracefully during backend slowdowns. Target 90%+ cache hit rate — anything below 85% indicates VCL misconfiguration or too many uncacheable blocks. Use varnishlog to trace cache misses and identify which requests bypass cache and why. Implement cache warming scripts that crawl your sitemap after deployment so visitors never hit an uncached page.
Tune Redis for Object Cache and Sessions
Configure Redis with separate databases: db0 for object/page cache (allkeys-lru eviction) and db1 for session storage (noeviction — sessions must never be evicted mid-checkout). Set maxmemory to 256MB–1GB depending on catalog size, monitoring with redis-cli INFO to ensure hit rates stay above 95%. Use Unix sockets instead of TCP for same-server deployments (saves 10–20% latency). Disable RDB persistence for the cache database (it regenerates automatically) but consider enabling it for sessions. Configure Redis Sentinel or Redis Cluster for high-availability in production. Monitor eviction counts — if evictions are frequent, increase maxmemory or audit what's filling the cache.
Optimize PHP-FPM and OPcache
Tune PHP-FPM worker count based on available RAM: each Magento worker consumes 128–256MB. Formula: (available_RAM × 0.7) / average_worker_memory = max_children. Set pm.max_spare_servers to 75% of max_children for traffic spikes. Configure OPcache with opcache.memory_consumption=256, opcache.max_accelerated_files=65536 (Magento has thousands of PHP files), opcache.validate_timestamps=0 in production (clear manually on deploy), and opcache.interned_strings_buffer=32. Enable opcache.preload for PHP 8.1+ to pre-compile Magento's most-used classes. Verify OPcache hit rates with opcache_get_status() — they should be 99%+.
Audit and Eliminate Extension Bloat
Magento's extension marketplace is both its strength and its performance weakness. Each extension adds database tables, queries, admin overhead, front-end JavaScript/CSS, and event observers/plugins that intercept core logic. Profile each extension: disable one at a time in a staging environment and measure the TTFB and page load difference. Remove unused extensions entirely — even disabled extensions still load configuration XML. Check for extensions that fire on every page load vs. only when needed (e.g., a shipping calculator extension that loads JavaScript on the homepage). Use bin/magento dev:di:info to trace plugin chains and identify extensions that intercept hot code paths. Target: fewer than 30 active third-party extensions for best performance.
Optimize MySQL/MariaDB Queries and Indexes
Enable the slow query log (long_query_time=1) and analyze the top 20 slowest queries. Common Magento issues: missing indexes on EAV attribute tables, orphaned catalog data from deleted products inflating table sizes, unoptimized flat catalog generation, and category/product count queries scanning full tables. Set innodb_buffer_pool_size to 70% of available RAM, innodb_log_file_size to 256MB–1GB, and query_cache_size=0 (query cache is deprecated and harmful in MySQL 8.0+). Run Magento's built-in indexer in 'Update by Schedule' mode (not 'Update on Save') to prevent write amplification. Clean orphaned data with n98-magerun2: catalog:images:remove-orphans, customer:cleanup.
Tune Elasticsearch/OpenSearch for Catalog Performance
Elasticsearch powers category pages, search results, and layered navigation — the most visited page types on e-commerce sites. Configure proper analyzers: use edge_ngram for autocomplete, standard analyzer for full-text search, and keyword type for filterable attributes. Optimize index settings: number_of_replicas=1 for read performance, refresh_interval=30s (not the default 1s) for better indexing throughput, and max_result_window appropriate for your catalog size. Create custom mappings for frequently filtered attributes. Monitor query latency with /_nodes/stats — individual queries should complete in under 50ms. For large catalogs (100K+ SKUs), consider separate search and product-detail indexes.
Migrate to Hyvä Theme (or Optimize Luma)
The Hyvä theme is the single biggest front-end optimization available for Magento. It replaces RequireJS and KnockoutJS (the two heaviest Luma dependencies) with Alpine.js and Tailwind CSS, reducing front-end JavaScript from 300KB+ to under 50KB. This eliminates most INP issues, dramatically improves LCP by removing render-blocking module initialization, and simplifies the development model. Migration cost: 2–8 weeks depending on customization complexity. If staying on Luma: optimize RequireJS configuration with advanced bundling (bin/magento setup:static-content:deploy with --strategy=compact), generate critical CSS for above-fold rendering with tools like Penthouse, lazy-initialize KnockoutJS components with intersection observers, and break long tasks in custom JavaScript using requestIdleCallback.
Pass Core Web Vitals on Magento
LCP: Fix server-side first — Varnish FPC must be working (check X-Cache header), then preload hero/banner images with <link rel="preload" as="image">, inline critical CSS, and defer non-critical RequireJS bundles. Target: hero image loaded within 2.5 seconds on mobile 4G. INP: The biggest opportunity is Hyvä theme migration. On Luma, optimize RequireJS bundling, lazy-initialize KnockoutJS components on interaction rather than page load, break add-to-cart and size/color selector handlers into async chunks, and use web workers for heavy computation. CLS: Reserve CSS min-height for ESI blocks (Varnish hole-punched areas render after initial paint), add explicit width/height to all product images, use font-display:swap with size-adjusted fallback fonts, and avoid auto-playing carousels above the fold. Test category pages and PDPs separately — they are the hardest templates to pass CWV on due to interaction complexity.
Want us to handle these optimizations?
Request an audit for your Magento site and see results in days, not months.
Magento in 2026: Updates & Future Trends
Magento's performance landscape is evolving rapidly in 2026. Adobe Commerce Cloud is investing heavily in edge computing — deploying Fastly's Compute@Edge for dynamic content assembly at the CDN layer, reducing origin requests by 40–60%. PHP 8.3/8.4 JIT compilation delivers 15–25% execution speed improvements for Magento's computation-heavy operations (EAV attribute loading, price calculation, rule evaluation). Hyvä theme adoption continues accelerating — over 35% of new Magento projects now choose Hyvä, and the ecosystem of Hyvä-compatible extensions has grown to cover 90%+ of common use cases. GraphQL and PWA Studio maturation enables headless architectures where the Magento backend serves data via API while a React/Vue frontend handles rendering — achieving sub-second page transitions. OpenSearch is replacing Elasticsearch in many deployments (Adobe Commerce 2.4.6+ ships with OpenSearch by default), offering better performance for large catalogs with improved vector search for AI-powered product recommendations. HTTP/3 and QUIC adoption by CDN providers means faster initial connections, particularly benefiting mobile users on unstable networks. The key trend: Magento's optimization is shifting from 'make the monolith faster' to 'decompose into optimized services' — caching at the edge, search via dedicated engines, rendering via headless frontends, with the PHP application handling business logic and orchestration.
Need help with Magento speed?
Our team specializes in Magento performance optimization. Request an audit and see exactly how much faster your site could be.
