How to cache Symfony responses with Cloudflare for free

How to cache Symfony responses with Cloudflare for free banner

Caching is a great way to speed up your website and reduce your server load. Why waste energy on pages that rarely change?

What is HTTP caching?

HTTP caching is a technique used in web communication to store and reuse previously fetched web resources, such as web pages, images, or other files, to reduce the need for redundant requests to the web server.

It helps improve website performance, reduce server load, and decrease page load times.

Caching works by saving a copy of a resource the first time it's requested and then serving that copy for subsequent requests until the cached version expires or becomes invalidated. This process helps save bandwidth and improve the overall user experience when browsing the internet.

What is the difference between private and public cache?

Private caches are for individual users and contain personalized or user-specific data, while public caches are for shared resources accessible by multiple users and usually store static or publicly accessible content.

If a response contains personalized content and you want to store the response only in the private cache, you must specify a private directive.

Cache-Control: private

The public response directive indicates that the response can be stored in a shared cache.

Cache-Control: public

You can read more about caching on developer.mozilla.org - HTTP caching.

What is the default Cloudflare cache behavior?

Cloudflare caches based on file extension and not MIME type.

Cloudflare does not cache HTML by default. It must be enabled manually.

By default, most images and static file extensions are cached, for example, GIF, PNG, WEBP, JPEG, CSS, JS, and more.

To indicate if a response is cached, Cloudflare has the CF-Cache-Status header showing whether a resource is cached.

To read the response headers, you can use Chrome developer tools -> Network tab

Chrome developer tools network tab read cache cloudflare

How to cache Symfony Responses with Cloudflare?

Add your website to Cloudflare

First, you'll need to have your website added to Cloudflare with your traffic Proxied through Cloudflare. To validate this, navigate to Cloudflare dashboard -> select your website -> DNS -> Records and make sure your Proxy status is Proxied.

cloudflare proxy status proxied

Return the proper cache headers from in the Symfony Response

Ensure you have configured max-age, and your response is set to public to tell Cloudflare that the resource can be cached.

class PostController extends AbstractController
{
    #[Route('/{slug}.html', name: 'post.view')]
    public function view(Post $post)
    {
        $response = $this->render('default/index.html.twig', []);

        $response->setPublic();
        $response->setMaxAge(86400);
        $response->headers->addCacheControlDirective('must-revalidate', true);

        return $response;
    }
}

HTTP Cache and User Sessions

Note that if you access the session, for example, by calling $this->getUser(), the response is automatically set to private, telling Cloudflare to skip the cache. You can read more about HTTP Caching and User Sessions in the official Symfony docs.

You can use this internal header to disable the default behavior for user session caching:

use Symfony\Component\HttpKernel\EventListener\AbstractSessionListener;

$response->headers->set(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER, 'true');

Enable caching of HTTP resources in Cloudflare

Cloudflare doesn't cache HTML resources by default. To enable this functionality, you need to create a custom Cache Rule.

Navigate to Cloudflare -> choose your website -> Caching -> Cache Rules and add a custom cache rule. Here is an example

cloudflare cache rule http cache html resources

This example will cache all resources if a proper cache tag exists and the cookie does not contain PHPSESSID.

The cookie rule is needed because, without it, logged users can potentially see cached content. Which in most cases is not desirable because the content is usually altered for logged users. 

If the user is logged in or a session is used, a cookie named PHPSESSID is created. This is the default cookie name for PHP applications.

Validate your pages are cached

Now, after you've configured your response headers and Cloudflare rules, you need to validate if your response is cached correctly. Open a page in the Incognito mode and check if, after the second refresh Cf-Cache-Status: header is present.

You can also use a tool like SpeedVitals - TTFB.

Cloudflare cf cache status

If you see Cf-Cache-Status: HIT - this means your page is served from Cloudflare. Good job!

You saved server resources, bandwidth, and your page load time decreased substantially.

What if my content changes frequently?

If you content changes frequently, you'll need to invalidate your cache before the TTL expires. This can be achieved by using CloudFlare's Purge Cache functionality. Here is how you can implement CloudFlare API Cache purge by URL.

Where CloudFlare stores the cached resources?

By default, CloudFlare stores the cached resources in the nearest Cloudflare server relative to the request location. For example, when requesting a resource from Sofia, Bulgaria, CloudFlare cache is stored in Warsaw, Poland. If the same already cached resource is requested from the United States - the cache in Poland will not be used by default and the resources will be requested from the origin. If you want to optimize that, you can enable Smart Tiered Caching Topology in Cloudflare.

What is Smart Tiered Caching Topology?

When Smart Tiered Caching is enabled, CloudFlare will search for a cached resource in its network before making a request to the origin server. This functionality can be enabled for free in Cloudflare -> Caching -> Tiered Cache -> Tiered Cache Topology.

CloudFlare tiered Caching Topology

You can read more about Cloudflare Smart Tiered Cache in their blog.

Conclusion

Leveraging CloudFlare HTTP cache will significantly improve your website performance and will decrease your server utilization.

By using HTTP cache, you can serve millions of requests per day with only a few requests to your server. That is big power!