Static Caching on Craft Cloud

All of Craft’s default caching features work as you would expect on Craft Cloud.

To supplement this, we provide a static caching system that automatically detects (and purges!) cacheable HTML responses. These static page caches are created and invalidated using the same mechanism as Craft’s own template caches—so any time an element is updated, Cloud knows exactly which pages to purge.

Static Cache vs. Template Caches #

Cloud’s static cache operates on full pages, which means that either the entire page is cached, or the entire page is served by your application. Whether you use additional caching strategies in your templates or back-end is up to you!

Craft’s built-in {% cache %} tag can be combined with static caching—but because the caches are invalidated at the same time, they may be redundant. If you have a highly-dynamic front-end that isn’t possible to cache statically, the normal template cache system is a great option for caching parts of a page.

Most Craft features that rely on dynamic rendering are already set up to bypass the cache, including the entire control panel, live preview, any front-end pages that use the session or cookies.

Opting Out #

If you would like to explicitly flag a template or response as being ineligible for full-page caching, set the Cache-Control header. In Twig, this can be accomplished with the {% header %} tag…

{% header 'Cache-Control: no-store' %}
{# …or, to be equivalent with the PHP function below… #}
{% header 'Cache-Control: no-cache, no-store, must-revalidate' %}

…or in PHP, using the Response component available from any controller:

public function actionSaveWidget(): Response
    // ...


This also sets Expires and Pragma headers.

If you would like to keep your templates in sync with Craft’s internal behavior, you can call the same method:

{% do %}

Force Caching #

If requests are missing the static cache (indicated by a Cf-Cache-Status: MISS response header) despite meeting the criteria above, and you know that a page should be cacheable, you can explicitly send cache headers:

{% do %}

Craft also sends the appropriate cache invalidation tags so that it can purge the page, later.

Manually caching a page in this way can leak user-specific information. This is only appropriate for use when you are absolutely sure that a page includes no personal details or customizations!

Custom Tags #

Send the special Cache-Tag header to tag responses that you want to be able to purge later, with a known key:

{% do'Cache-Tag', 'my-custom-tag') %}

Previously, we used the Twig {% header %} tag to set the Cache-Control header. This is fine in situations where the template can dictate the final value of a header—but tagging pages for Cloudflare’s cache must be done additively with the response’s header collection, without replacing ones that may have been set earlier in the request.

From a controller, you access headers via the same response instance:

$headers = $this->response->getHeaders();
$headers->add('Cache-Tag', 'custom-cache-tag');

Keep in mind that custom tags can only be purged manually, or via a subsequent HTTP response with a Cache-Tag-Purge header. This means that a custom tag sent from a template cannot be purged by the same template, as subsequent requests will be served from the cache and not trigger evaluation. The most reliable way to purge a tag is by sending the appropriate header when a control panel user changes the underlying data.

The format for Craft’s built-in element cache tags is not part of its public API, so we do not recommend attempting to reconstruct them for the purposes of selectively purging caches.

Cache-Tag headers are stripped from the HTTP response at our edge nodes.

Manual Purging #

If you would like to clear your environment’s static page cache, visit the Utilities screen, check Cloud Static Caches, then Clear Caches.

Applies to Craft CMS 4 and Craft Cloud.