Properly setting up Cloudflare caching for faster TTFB

Properly setting up Cloudflare caching for faster TTFB

When doing pagespeed audits, there often is a common pitfall that I see happening across different webshops. If you're using Cloudflare, then this might help you out as well.

While the Cloudflare website isn't passing Core Web Vitals, their services can actually help you improve the performance, bounce and conversion of your very own webshop. But only if done right, so let's dive in.

The Cloudflare caching bottleneck

A cf-cache-status: DYNAMIC response header is what I'm often seeing. To double test, I refresh the page and look once more at this Cloudflare cache status header. The reason is simple: if Cloudflare was configured correctly, then pages should be cached and the second pagehit should return a cached result, indicated with a cf-cache-status: HIT response header.

When it doesn't, then I know I already found one of many issues when auditing a webshop. Especially on pages that don't tend to change much within a short timespan.

What about dynamic contents (pricing, stock)

And as a developer by origin, I get that some parts of a page should always remain dynamic. But are you ready to sacrifice the complete early user engagement because some portions of your shop are dynamic? I bet you don't when knowing the impact towards bounce and revenue.

So, if you do have changing prices depending on (logged in) clients, changing stocks/product availability, then be sure to render them using additional API calls on top of server side rendered pages. You then get to benefit from both:

  • fast served pages (when caching has been enabled correctly);
  • while still having dynamic contents depending on the page type.

Configure Cloudflare HTML caching

So, when using or moving to Cloudflare, be sure to enable Cloudflare caching.

Cloudflare won't cache HTML pages by default

This one is quite important to know: while Cloudflare will cache static resources such as images, stylesheets and JavaScript, HTML pages don't get cached by default. And this makes sense: Cloudflare doesn't blindly know if meant these pages to be dynamic. Maybe you're showing stock exchange data, or live soccer stands. I then personally wouldn't server side render this, but that's another story. And once again: Cloudflare doesn't know your stack nor strategy, it only receives the HTML.

So, when not enabling caching for HTML pages, Cloudflare will have to loop back to your origin server. It's likely this actually increases your TTFB instead of improving it. I've seen real user data where the 25% worst experiences improved, but the other already ok-ish 75% TTFB experiences actually regressed. You wouldn't notice when only looking at 75th percentile data like PageSpeed Insights field data is showing you.

Steps to configure Cloudflare caching

Glad you reached this point, as this is where we'll be making a TTFB difference. The following steps might guide you towards creating the necessary Edge Cache TTL page rules:

  1. Log in to your Cloudflare dashboard.
  2. Select the domain where you want to add the page rule.
  3. Click the Rules icon on the page top area;
  4. Click Create Page Rule button;
  5. Insert a url path ( for example* ) in the top input text box. Asterix is used as wildcard;
  6. Select Cache Level in Pick a Setting drop-down list;
  7. Select Cache Everything in the Select Cache Level drop-down list;
  8. Click the Save and Deploy button to save and deploy the changes;
  9. You can select page rule trigger order in the Order selection list;
  10. If there are multiple page rules, the most top page rule in the page rule list will be triggered first.
  11. When visiting the webpage, you should see the cf-cache-status: HIT response header, or cf-cache-status: MISS when you're the first visitor visiting this page. Be sure to refresh the page and check the response headers once again.

TTFB improvement after implementing Cloudflare

After setting up a proper caching strategy using the information above, you should see chances within real user experiences. This should be data to look at instead of for example an online TTFB test or Lighthouse reports as real users out there will all be visiting your site or shop under different circumstances.

So, let's dive into real UX changes of one of the optimizations I was involved with. They implemented the above to have pages return a cf-cache-status: HIT response header. And they saw the following across 40,053 mobile pageviews:

  • Overall, they went from 1530ms to 930ms. Still not green TTFB results, but already a 39.2% improvement at the mobile 75th percentile;
  • There was a 55% improvement at the median (50th percentile) as they went from 1100ms to 495ms;
  • And even the pageviews that were already ending up in the 10% fastest experiences saw an improvement: the 10th percentile improved by 61.7% due to a previous 308ms TTFB experiences dropped to 118ms.

Not seeing cf-cache-status: HIT

When you still see the cf-cache-status: DYNAMIC response header, then Cloudflare thinks it isn't allowed to cache contents. That's because Cloudflare respects the cache headers of the origin web server.

Important to know is that Cloudflare does not cache the resource if the Cache-Control header is set to private, no-store, no-cache, or max-age=0 or if there is a cookie in the response. Additionally, the Expires header should be set in the future.

It can be either your hosting, plugins or platform itself that might be changing the Cache-Control header. Be sure to check your own headers and investigate where this header is coming from when Cloudflare isn't caching your pages.

Ignore query strings

Although part of a paid plan, be sure to ignore common query strings to improve TTFB experiences for an even larger portion of visitors.