
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.
| Layer | Listens on | Job |
|---|---|---|
| TLS terminator (load balancer, nginx or a CDN) | 443 | Decrypts HTTPS, because Varnish does not support SSL |
| Varnish | 80 | Serves cached pages, forwards misses, handles purges |
| nginx + PHP-FPM | 8080 | Runs 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:
varnishd -VStep 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:
sudo nginx -t && sudo systemctl reload nginxNext, 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:
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-reloadDo 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:
bin/magento config:set --scope=default --scope-code=0 system/full_page_cache/caching_application 2The 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
localhostand8080). - 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.

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:
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.vclA few details from the source code are worth knowing:
--export-versionaccepts 4, 5, 6 and 7, and defaults to 6. The newest template,varnish7.vcl, states a minimum of Varnish 7.0, so pass7for a current Varnish install. There is no separate Varnish 8 template.--access-listcan 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:
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 varnishWhat the generated VCL does for you
- Health probe. Varnish polls
/health_check.phpevery 5 seconds. Magento ships this file inpub/. 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
/customerand/checkoutare passed straight to the backend, and only GET and HEAD are cached. - Tracking parameters stripped.
utm_*,gclid,fbclidand similar parameters are removed from the cache key, so campaign links do not fragment the cache. - Static files passed by default.
/staticand/mediaare 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:
bin/magento setup:config:set --http-cache-hosts=127.0.0.1:80
bin/magento cache:flushUse 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.

Step 5: verify the cache is working
Request a cacheable page twice and read the headers. Adobe's guide shows this command:
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:
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-hostsis set and that the web servers' IPs are in the access list. Test withvarnishlog -g request -q 'ReqMethod eq "PURGE"'. - 503 Backend fetch failed. Check that
/health_check.phpreturns 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
- Add the
varnish:vcl:generatecommand to your deployment so the VCL always matches the installed Magento version. - Track hit rate in
varnishstatbefore and after changes to layouts or blocks; a non-cacheable block can make a whole page uncacheable. - Put a CDN in front for static assets and TLS, and keep Varnish focused on HTML.
- 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 withbin/magento varnish:vcl:generateand set purge hosts withbin/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-Debugresponse header forHITorMISS. Adobe also suggests clearingvar/page_cacheand confirming it stays empty while you browse.Does Varnish cache the cart and checkout?
No. The generated VCL passes
/customerand/checkoutURLs 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.
Your next customer could start right here.
Introduce your tool, product or business to readers exploring technology.
Explore placements and request a private quote
Sources
- Configure Varnish — Adobe Experience League
- Configure Commerce to use Varnish — Adobe Experience League
- Final verification — Adobe Experience League
- Use Varnish cache — Adobe Experience League
- System requirements (Adobe Commerce) — Adobe Experience League
- GenerateVclCommand.php and varnish7.vcl (magento/magento2) — GitHub
- 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.
More from Cloudsoft Zone

Troubleshooting guideCodeIgniter
CodeIgniter 4 validation not working? 9 causes and fixes
Fix CodeIgniter 4 validation problems fast: wrong input source, lost errors after redirect, permit_empty, strict JSON rules, is_unique placeholders and more.
By Cloudsoft Zone

TutorialPHP
PHPStan tutorial: catch PHP bugs before production with levels
Install PHPStan 2.3, choose a rule level, adopt a baseline for legacy code and fail CI only on new errors, with real output from a worked PHP 8.5 example.
By Cloudsoft Zone

Resource guideResources
Cron syntax cheat sheet: crontab, GitHub Actions, Kubernetes
Cron syntax with tested expressions, the day-of-week trap, and how time zones and limits differ in crontab, GitHub Actions, Kubernetes and Laravel in 2026.
By Cloudsoft Zone
