Skip to main content

Cloudsoft Zone Build, deploy and scale with practical guides to PHP, Node.js, React, DevOps and AI automation. Explore the guides

Cloudsoft Zone
MagentoDevOpsTutorial

How to set up Varnish full-page cache for Magento 2.4.9

Set up Varnish in front of Magento 2.4.9: move nginx to 8080, switch the caching application, generate the VCL, configure purges and confirm cache hits.

Cloudsoft Zone

Updated 6 min read

Black server rack holding stacked rack-mounted servers and network equipment with status lights
Photograph: Mike Beltzner / CC BY-SA 2.0, via Wikimedia Commons
In this article

Varnish is the full-page cache Adobe recommends for production Magento stores, and setting it up takes four moves: put Varnish in front of the web server, switch Magento's caching application to Varnish, generate the VCL from Magento, and tell Magento where to send purge requests. Done right, Adobe says cacheable pages should load in under 150 ms. This tutorial walks through each step for Magento Open Source and Adobe Commerce 2.4.9, with the commands verified against Adobe's documentation and the magento/magento2 source.

How the pieces fit together

Adobe's reference architecture is simple. Varnish accepts HTTP traffic on port 80 and forwards cache misses to nginx on a backend port such as 8080. Cacheable responses are stored in Varnish, so repeat requests never reach PHP.

LayerListens onJob
TLS terminator (load balancer, nginx or a CDN)443Decrypts HTTPS, because Varnish does not support SSL
Varnish80Serves cached pages, forwards misses, handles purges
nginx + PHP-FPM8080Runs Magento using nginx.conf.sample

This guide is for self-hosted Magento Open Source and Adobe Commerce on-premises. Adobe Commerce on cloud infrastructure uses Fastly, a Varnish-based CDN service, to cache pages instead, so the steps below do not apply there. A single Varnish server is enough for most small and mid-sized stores; larger setups run several Varnish nodes behind a load balancer, and Magento can purge all of them.

Adobe's system requirements list Varnish 8 for 2.4.9, 2.4.8 and 2.4.7. Install Varnish from your distribution or the official Varnish packages, then confirm the version:

Shell
varnishd -V

Step 1: move nginx to the backend port

Change the nginx server block that includes Magento's nginx.conf.sample so it listens on 8080 instead of 80, then reload it:

Shell
sudo nginx -t && sudo systemctl reload nginx

Next, make Varnish listen on port 80. Packaged Varnish usually ships a systemd unit that listens on 6081, so override the start command. The cache size is an example; size it to your catalogue and RAM:

Shell
sudo systemctl edit varnish
# In the override file:
# [Service]
# ExecStart=
# ExecStart=/usr/sbin/varnishd -a :80 -f /etc/varnish/default.vcl -s malloc,2G
sudo systemctl daemon-reload

Do not restart Varnish yet. It needs Magento's VCL first.

Step 2: switch Magento to Varnish

In the Admin, go to Stores > Settings > Configuration > Advanced > System > Full Page Cache and set Caching Application to Varnish Caching. From the CLI, Adobe documents the equivalent:

Shell
bin/magento config:set --scope=default --scope-code=0 system/full_page_cache/caching_application 2

The value 2 is Varnish; 1 is the built-in cache. While you are on that screen, check the remaining Varnish fields:

  • Access list: hosts allowed to purge (default localhost).
  • Backend host and Backend port: your nginx origin (defaults localhost and 8080).
  • Grace period: how long Varnish may serve stale content when the backend is unhealthy (default 300 seconds).
  • TTL for public content: 86400 seconds by default.
Open server rack with dense bundles of network and power cables and white air conditioning ducts
Keep the topology simple: TLS in front, Varnish on port 80, nginx on 8080.

Step 3: generate the VCL from Magento

Never hand-write the VCL. Magento generates it with the right purge logic, cache-key rules and health probe. The Admin has export buttons on the Full Page Cache screen, but the CLI command is easier to script:

Shell
bin/magento varnish:vcl:generate \
  --export-version=7 \
  --backend-host=127.0.0.1 \
  --backend-port=8080 \
  --access-list=127.0.0.1 \
  --grace-period=300 \
  --output-file=/tmp/default.vcl

A few details from the source code are worth knowing:

  • --export-version accepts 4, 5, 6 and 7, and defaults to 6. The newest template, varnish7.vcl, states a minimum of Varnish 7.0, so pass 7 for a current Varnish install. There is no separate Varnish 8 template.
  • --access-list can be repeated to allow several purging hosts.
  • Without --output-file, the VCL is printed to standard output.

Back up the old file, install the new one and compile-check it before restarting:

Shell
sudo cp /etc/varnish/default.vcl /etc/varnish/default.vcl.bak
sudo cp /tmp/default.vcl /etc/varnish/default.vcl
sudo varnishd -C -f /etc/varnish/default.vcl > /dev/null && echo "VCL compiles"
sudo systemctl restart varnish

What the generated VCL does for you

  • Health probe. Varnish polls /health_check.php every 5 seconds. Magento ships this file in pub/. When the backend is unhealthy, grace mode serves stale pages instead of errors.
  • Long first-byte timeout. The backend has .first_byte_timeout = 600s, which avoids many 503 errors on slow pages.
  • Private pages bypassed. Requests to /customer and /checkout are passed straight to the backend, and only GET and HEAD are cached.
  • Tracking parameters stripped. utm_*, gclid, fbclid and similar parameters are removed from the cache key, so campaign links do not fragment the cache.
  • Static files passed by default. /static and /media are not cached unless you edit the template, because most stores serve them from a CDN or nginx directly.

Step 4: tell Magento where to purge

When you save a product, price or category, Magento sends a purge to Varnish. It needs the Varnish address for that:

Shell
bin/magento setup:config:set --http-cache-hosts=127.0.0.1:80
bin/magento cache:flush

Use host:port pairs separated by commas with no spaces for several Varnish servers, for example --http-cache-hosts=10.0.0.11:80,10.0.0.12:80. The port can be omitted when it is 80. The purge request arrives from your web servers, so their IPs must also be in the VCL's acl purge list; otherwise Varnish answers 405 Method not allowed.

Purges happen automatically when you add or edit categories, prices, products or promotional price rules, and when you clean, flush or refresh the cache from System > Cache Management or with bin/magento cache:clean.

A woman places a banknote into a miniature shopping cart beside a laptop on an office desk
Shoppers feel the difference: Adobe says cached pages should load in under 150 ms.

Step 5: verify the cache is working

Request a cacheable page twice and read the headers. Adobe's guide shows this command:

Shell
curl -I -v --location-trusted 'https://www.example.com/'

Look for X-Magento-Cache-Debug: MISS on the first request and HIT on the second. The current template sets this header in vcl_deliver, with UNCACHEABLE for pages Magento marked private. Adobe's guide says to use developer mode to see the debug headers; the template removes the Age header unless the backend sends X-Magento-Debug.

Then use Adobe's own definitive test. Clear Magento's built-in page cache directory, browse some cacheable pages and check it again:

Shell
rm -rf var/page_cache/*
# browse a few category and product pages, then:
ls var/page_cache/

If the directory stays empty, Varnish is serving the pages and Magento's file-based page cache is no longer used. To watch traffic live, varnishlog and varnishstat show requests, hits and backend fetches.

Gotchas

  • Wrong export version. The CLI defaults to the Varnish 6 template. On Varnish 7 or later, always pass --export-version=7.
  • HTTPS redirect loops. Varnish only sees HTTP. Your TLS terminator must send the SSL offload header that the template names (commonly X-Forwarded-Proto: https) so Magento knows the original request was secure.
  • Purges silently failing. If price changes do not appear, check that --http-cache-hosts is set and that the web servers' IPs are in the access list. Test with varnishlog -g request -q 'ReqMethod eq "PURGE"'.
  • 503 Backend fetch failed. Check that /health_check.php returns 200 through nginx on 8080, and that the backend host and port in the VCL match nginx.
  • Deleted cache directories. Adobe notes that if you manually delete var/cache, you should restart Varnish.
  • Regenerate after upgrades. Templates change between releases (the tracking-parameter list, for example). Regenerate the VCL after each Magento upgrade and diff it against production.

What to do next

  1. Add the varnish:vcl:generate command to your deployment so the VCL always matches the installed Magento version.
  2. Track hit rate in varnishstat before and after changes to layouts or blocks; a non-cacheable block can make a whole page uncacheable.
  3. Put a CDN in front for static assets and TLS, and keep Varnish focused on HTML.
  4. Pair Varnish with Valkey for the default cache and sessions, which Adobe lists for 2.4.9.

Frequently asked questions

  • Which Varnish version does Magento 2.4.9 support?

    Adobe's system requirements list Varnish 8 for 2.4.9, 2.4.8 and 2.4.7. Generate the VCL with --export-version=7, the newest template in the code base.

  • How do I enable Varnish in Magento from the command line?

    Run bin/magento config:set --scope=default --scope-code=0 system/full_page_cache/caching_application 2, then generate the VCL with bin/magento varnish:vcl:generate and set purge hosts with bin/magento setup:config:set --http-cache-hosts=<host:port>.

  • Why does Varnish not work with HTTPS on its own?

    Varnish does not support SSL. Terminate TLS in a load balancer, CDN or nginx in front of Varnish, and pass the SSL offload header so Magento builds secure URLs.

  • How can I tell if a Magento page came from Varnish?

    Check the X-Magento-Cache-Debug response header for HIT or MISS. Adobe also suggests clearing var/page_cache and confirming it stays empty while you browse.

  • Does Varnish cache the cart and checkout?

    No. The generated VCL passes /customer and /checkout URLs and all non-GET requests to the backend. Private blocks such as the mini cart are loaded separately for each customer.

  • What does the grace period do?

    It lets Varnish serve stale cached pages when the backend health check fails. Magento's default is 300 seconds, set in the Admin or with --grace-period.

Advertise on CloudSoftZone

Your next customer could start right here.

Introduce your tool, product or business to readers exploring technology.

Advertise with us

Explore placements and request a private quote

Sources

  1. Configure Varnish — Adobe Experience League
  2. Configure Commerce to use Varnish — Adobe Experience League
  3. Final verification — Adobe Experience League
  4. Use Varnish cache — Adobe Experience League
  5. System requirements (Adobe Commerce) — Adobe Experience League
  6. GenerateVclCommand.php and varnish7.vcl (magento/magento2) — GitHub
  7. Fastly services overview — Adobe Experience League

Written with substantial AI assistance. Facts checked against cited sources. Editorial policy.

Comments

No comments yet. Be the first to join the conversation.

Leave a comment

Every comment is read by a moderator before it appears. Your email address is never published; it is used only to contact you about this comment.

Never published. Used only to contact you about this comment.

Loading the security check…

Comments are moderated before publication.