How to Optimize Magento 2 Performance and Improve Page Speed

Magento 2 performance depends on proper configuration of caching, static content delivery, image optimization, and server-level tuning. Out-of-the-box settings are conservative and leave significant room for improvement. This guide covers the most impactful optimizations based on real-world store configurations.

Full Page Cache (FPC)

Full Page Cache is the single most impactful performance feature in Magento 2. When properly configured, FPC serves pages without executing any PHP code, reducing response times from seconds to milliseconds.

Understanding Cache Multipliers

FPC creates a separate cached version of each URL for every combination of customer group, store view, and currency. This means:

  • 10,000 product URLs × 4 customer groups × 4 store views = 160,000+ cache entries

For most stores, only the "NOT LOGGED IN" customer group needs cache warming, since logged-in customers represent a small fraction of traffic and their sessions change frequently.

Reducing Cache Entries

Enable "Use same cache for new visitor" in Stores → Configuration → System → Full Page Cache to prevent creating duplicate cache entries for new vs. returning visitors who are not logged in. This alone can cut the number of FPC entries significantly.

FPC Compression

Magento compresses cached HTML before storing it in the backend. The default compression threshold is 20,480 bytes (20 KB), meaning smaller pages are stored uncompressed.

Lower the threshold to 2,048 – 4,096 bytes to compress virtually all HTML pages. Typical HTML pages compress by 60–80%, reducing both storage requirements and network transfer time when using Redis or Varnish as the FPC backend.

See also: Redis Full Page Cache

JavaScript and CSS Optimization

Minification and Merging

Enable these settings under Stores → Configuration → Advanced → Developer → JavaScript Settings and CSS Settings:

  • Merge JavaScript Files: Yes
  • Enable JavaScript Bundling: No (often causes more problems than it solves)
  • Minify JavaScript Files: Yes
  • Move JS code to the bottom of the page: Yes
  • Merge CSS Files: Yes
  • Minify CSS Files: Yes

After changing these settings, deploy static content:

php bin/magento setup:static-content:deploy
php bin/magento cache:flush

Incremental Enabling

Some third-party extensions generate JavaScript that conflicts with merge or minification. If you encounter frontend issues after enabling these settings, turn them on one at a time:

  1. Enable CSS minification first -- this rarely causes issues
  2. Enable CSS merge
  3. Enable JS minification
  4. Enable JS merge last -- this is the most likely to expose conflicts

If a specific setting causes problems, leave it disabled and investigate which extension is incompatible.

Image Optimization

Images typically account for 50–80% of page weight. Optimizing images provides the largest improvement in perceived page load time.

Key Settings

  • Quality: Set JPEG quality to 80%. The visual difference between 80% and 100% is negligible, but file size drops by 40–60%
  • Format: Use WebP where possible. WebP images are 25–35% smaller than equivalent JPEGs
  • Lazy loading: Enable lazy loading for images below the fold to reduce initial page load time

WebP Conversion

WebP conversion is a background process that runs via cron. After enabling WebP, allow time for the cron to process existing images. For large catalogs, this can take several hours.

Validate that image processing libraries are correctly installed:

php bin/magento mirasvit:optimize-image:validate

This checks for GD, Imagick, and WebP support in the PHP installation.

Redis Configuration

Redis is the recommended cache backend for both default cache and FPC in Magento 2. Incorrect Redis configuration causes cache eviction issues that degrade performance unpredictably.

Eviction Policy

The most common Redis misconfiguration is using volatile-lru as the eviction policy. This only evicts keys with an expiration time set. Magento stores some cache entries without expiration, creating "immortal" keys that Redis cannot evict when memory is full.

Solution: Use allkeys-lru as the eviction policy:

# In redis.conf
maxmemory-policy allkeys-lru

This allows Redis to evict any key when memory pressure is high, preventing out-of-memory errors and stale cache issues.

Separate Redis Instances

Use separate Redis instances (or at least separate databases) for:

  • Default cache (db 0)
  • Full Page Cache (db 1)
  • Session storage (db 2)

This prevents cache flushes from destroying sessions and allows independent memory management.

Cache Clearing Order

When troubleshooting or deploying, clear caches in the correct order:

# 1. Clean Magento cache tags
php bin/magento cache:clean

# 2. Flush entire Magento cache storage
php bin/magento cache:flush

# 3. Flush Redis completely (if using Redis)
redis-cli -n 0 FLUSHDB   # default cache
redis-cli -n 1 FLUSHDB   # FPC

# 4. Purge CDN/Varnish if applicable

Running cache:clean removes only invalidated entries by tag. Running cache:flush empties the entire cache storage. For a full reset, flush Redis directly and purge any CDN or Varnish layer.

Profiling Performance

Before optimizing, identify where time is being spent. Use the built-in Magento profiler to find slow blocks and queries:

See also: How to Enable Magento 2 Profiler

Loading...