Skip to content

What gets cached

Edge Caching caches anonymous GET and HEAD requests for successful pages and redirects, for one hour. Everything personal or state-changing goes straight to the origin. This page describes the rules in the order the site’s VCL applies them, and how to diagnose a page that is never cached.

Each request reaching the site’s Varnish instance goes through these steps, in this order. As soon as a step passes or blocks the request, evaluation stops there.

  1. Development Mode. When enabled, every request is passed to the origin and nothing is cached.
  2. Routing. If the path matches one of your extra routes, the request is sent to that route’s backend instead of the main origin. All the following rules still apply.
  3. Authorization header. Requests carrying HTTP authentication are passed.
  4. Excluded visitor IPs are passed.
  5. Geo blocking. Requests from a blocked country receive a 403.
  6. Excluded cookies, URL paths and user agents are passed.
  7. XML-RPC and trackbacks (/xmlrpc.php, /wp-trackback.php) are blocked with a 403 when XML-RPC blocking is enabled, and passed otherwise.
  8. Firewall rules return a 403: AI crawlers, vulnerability scanners, blocked user agents, empty user agents, sensitive files, PHP files in uploads and author enumeration, each when enabled.
  9. wordpress_no_cache cookie. With Exclude DONOTCACHEPAGE Constant enabled, requests carrying this cookie are passed.
  10. Cookies are removed from the request.
  11. Query string cleaning strips tracking parameters, or the whole query string if configured.
  12. Method check. Anything other than GET or HEAD is passed.
  13. Cache lookup. A hit is answered from memory; a miss is fetched from the origin.

These defaults are tuned for WordPress and WooCommerce. You can add your own under Cache Rules in the admin.

Rule Default values
Excluded cookies wordpress_logged_in, wordpress_sec_*, wp-postpass, woocommerce_cart_hash, woocommerce_items_in_cart, woocommerce_cart, wp_woocommerce_session
Excluded URL paths /wp-admin, /wp-login.php, /wp-json/, /feed, sitemaps (sitemap*.xml), /login, /cart, /checkout, /my-account
Stripped query parameters utm_source, utm_medium, utm_campaign, utm_content, utm_term, fbclid, gclid, msclkid

Paths are matched as regular expressions against the URL. A path rule starting with ^ matches only at the beginning of the URL, so ^/cart covers /cart/ and /cart/?step=2 but not /product/cart-cover/.

After the bypass checks, all remaining cookies are removed from the request before the cache lookup. A cached page therefore never varies by cookie, and a cookie never causes a page to bypass the cache unless it is listed in Exclude Cookies.

If your theme or a plugin reads a cookie to change the page for anonymous visitors, such as a currency switcher, a language selector or an A/B test, add that cookie to Exclude Cookies. Otherwise every visitor receives whichever version was cached first.

Tracking parameters are removed before the lookup, so /pricing/?utm_source=newsletter and /pricing/ share one cache entry, and the origin receives the URL without them. Browser-based analytics still see them; see Analytics and tracking tools for the plugins that read them on the server.

Any other parameter creates a separate cache entry: /shop/?color=red and /shop/?color=blue are cached independently. If your site never uses query strings to change content, Strip all query strings collapses every variant into one entry. Do not enable it on sites where query strings matter, such as search results or filtered product listings.

Origin response Behavior
200, 301, 302 Cached for 1 hour, regardless of max-age, plus the grace period when Always Online is enabled
Cache-Control: no-cache, no-store or private Never cached, whatever the status
404 Not cached
5xx Not cached. Visitors get the maintenance page, or a stale copy when Always Online has one
Other statuses (307, 410, …) Varnish defaults: the response’s own Cache-Control or Expires, otherwise two minutes

The one-hour lifetime is set by the platform: a max-age or s-maxage from the origin neither shortens nor extends it. To keep a page out of the cache, send Cache-Control: private or no-store, or add its path to Exclude URL Paths. To refresh a page after a change, purge it (see How the cache is refreshed).

Set-Cookie headers are removed from cached responses, so one visitor’s session cookie is never served to another. A consequence is that a cached page cannot set cookies. Responses that are passed, or marked private or no-store, keep their Set-Cookie headers.

Header Meaning
X-Cache: HIT Served from cache. X-Cache-Hits shows how many times this cached copy has been served.
X-Cache: MISS Fetched from the origin, either a cache miss or a passed request.
X-Cache: BLOCKED Rejected by a site firewall rule.
X-Served-By Identifies responses served by the site’s Varnish instance.

Inspect them with:

Terminal window
curl -sI https://example.com/ | grep -i '^x-'

If a page returns X-Cache: MISS on every request, check these causes in order:

  1. Development Mode is enabled for the site.
  2. You are logged in. Your browser sends wordpress_logged_in, which is excluded. Test from a private window or with curl.
  3. The path matches an excluded path, including the defaults above.
  4. The origin sends Cache-Control: private, no-cache or no-store. Some plugins and WooCommerce session handling do this on every page. Check with curl -sI against the origin.
  5. The request is not a GET or HEAD, or carries an Authorization header.
  6. The URL varies. Different query strings are different cache entries; a unique parameter on every request means every request is a miss.
  7. The response is a 404 or 5xx, which are never cached.