Always getting X-Drupal-Cache: MISS? Check for messages

I spent about an hour yesterday debugging a Varnish page caching issue. I combed the site configuration and code for anything that might be setting cache to 0 (effectively disabling caching), I checked and re-checked the /admin/config/development/performance settings, verifying the 'Expiration of cached pages' (page_cache_maximum_age) had a non-zero value and that the 'Cache pages for anonymous users' checkbox was checked.

After scratching my head a while, I realized that the headers I was seeing when using curl --head [url] were specified as the defaults in drupal_page_header(), and were triggered any time there was a message displayed on the page (e.g. via drupal_set_message()):

X-Drupal-Cache: MISS
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Cache-Control: no-cache, must-revalidate, post-check=0, pre-check=0
X-Content-Type-Options: nosniff

On this particular site, the error_level was set to 1 to show all errors on the screen, and the page in question had a PHP error displayed on every page load.

After setting error_level to 0 ('None' on the /admin/config/development/logging page), Drupal sent the correct cache headers, Varnish was able to cache the page, and my sanity was restored.

Kudos especially to this post on coderwall, which jogged my memory.

Other potential reasons a page might not be showing as cacheable:

  • A form with a unique per-user token may be present.
  • An authenticated user is viewing the page (Drupal by default marks any page view with a valid session as no-cache).
  • Someone set \Drupal::service('page_cache_kill_switch')->trigger(); (Drupal 8), or drupal_page_is_cacheable() (Drupal 7).
  • Some configuration file that's being included is either setting cache or page_cache_maximum_age to 0.


That's funny timing. Alex ran into this exact issue last week on a site. In this site's case, the theme didn't actually display Drupal messages anywhere so the error messages could never be seen. Even not displayed, these still caused misses.