OCMLABS/MODULE-CLOUDFLARE · VARNISH

Running Cloudflare in front of Varnish with a Cloudflare-aware VCL exported from Magento

  • Magento
  • Adobe Commerce
  • Hyvä

The problem with stock VCL

Magento’s generated Varnish VCL does two things in vcl_deliver that defeat an edge cache in front of it: it rewrites Cache-Control to no-cache on every response, and it removes the tag header. Cloudflare in front of stock Varnish sees nothing it can cache, so HTML is served by Varnish only and Cloudflare adds latency without adding a cache.

What the module does in Varnish mode

When Magento’s caching application is set to Varnish (Stores > Configuration > Advanced > System > Full Page Cache), the module changes how it works:

  • It leaves Magento’s own headers and cookies to Varnish. No Cache-Control rewrite and no cookie stripping happen in PHP, because Varnish already does both.
  • It still adds its edge marker (an internal TTL header) and the Cache-Tag header to responses Magento considers public, so the VCL can see them.
  • The VCL makes the edge decision, as described below.

Edge caching in Varnish mode covers default-context pages only. Vary Handling Cache key is not supported behind Varnish; leave it at Bypass.

Export the VCL

Terminal window
bin/magento ocmlabs:cloudflare:vcl:export --varnish-version=6 --output=/tmp/default.vcl
varnishd -C -f /tmp/default.vcl > /dev/null

The second line is a syntax check; run it before loading the file. Varnish versions 4, 5, 6 and 7 are supported with --varnish-version; 6 is the default. Without --output the VCL is printed to standard output.

Download Cloudflare VCL on the Health tab produces the same file from the admin.

What changes in the exported VCL

The file is Magento’s own generated VCL for the chosen version, with two additions:

  1. In vcl_recv, a note is made of whether the request carries the X-Magento-Vary cookie.
  2. In vcl_deliver, a response that carries the module’s edge marker gets Cache-Control: public, max-age=0, s-maxage=<ttl> instead of Magento’s no-cache rewrite, and Cache-Tag is left in place for Cloudflare. The marker itself is removed before the response leaves Varnish.

The marker branch is guarded. It skips any response that is already private or no-store, anything Varnish itself marked uncacheable, and any request that carried the vary cookie. A page Varnish would not cache is never made cacheable at the edge.

CAUTION /

Varnish keeps objects it stored before a configuration change until they expire or are purged. After changing Bypass Paths or turning edge caching off, purge Varnish as well as Cloudflare (bin/magento cache:clean full_page does both when Purge Everything on Full Page Cache Clean is on).

Checking it works

The “Origin sends edge cache headers” health check fetches a page straight from Storefront Origin (set it to the Varnish address) and reports whether Cache-Control and Cache-Tag arrive intact. If it fails after you loaded the exported VCL, something else between Varnish and Cloudflare is still stripping them.

Terminal window
curl -sI -H "Host: www.example.com" http://varnish-host/some-category.html | grep -iE "cache-control|cache-tag"

If you would rather not change the VCL

Leave Enable Edge Caching of HTML off. Purging, the cache rules, the health checks and analytics all keep working; only HTML stays on Varnish instead of the edge.

See also

In this module