First of all I don’t have ‘Always on’ enabled and I am using Argo tunnel to connect to my local machine for testing. Also I thought this would be a simple thing to understand but I can’t seem to find a solution.
Let’s say my origin serves a file /ostrich.png with header cache-control: public, max-age=30.
I’ll get cf-cache-status: HIT response up until when 30 seconds has passed and then it will refresh the resource.
I then take my server completely down.
After 30 seconds I’m seeing cf-cache-status: STALE instead of an expected 5xx origin error message. There’s a 2 second delay as it makes an attempt to connect and fails.
This is the behavior I would want if I had set stale-while-revalidate but I didn’t set that header for this resource. The help says:
The resource was served from cache but is expired. Cloudflare couldn’t contact the origin to retrieve the updated resource.
But I don’t want this. I want an error if the server is down after the resource has expired. The behavior I’m seeing is effectively the ‘Always on’ behavior without the banner.
I originally was trying to implement stale-while-revalidate and stale-if-error but without setting either of those options I’m effectively getting an infinite time serving stale resources. What am I missing?
You shouldn’t confuse browser cache control versus cloudflare cdn cache TTL values. Cloudflare CDN cache has a minimum CDN cache TTL based on the CF plan you’re on. So Free = 2hrs, Pro = 1hr, Business = 30min and Enterprise can have 1 second.
So unless you’re on Cloudflare Enterprise plan, setting cache-control max-age will not let you expire CDN cache after 30 seconds. Free plan would only expire CDN cache after 2hrs and browser cache would be either what Cloudflare default browser cache time is or your origin max-age - whichever is longer.
What does the Browser Cache TTL do?
The Browser Cache TTL specifies how long cached files will remain in your visitor’s browser cache. This expiration time is what Cloudflare will set unless longer time periods are specified at your web server.
A longer expiration time ensures faster load times for repeat visitors. However, a longer expiration time also means slower update times if those files are modified.
That is working as expected for browser cache which isn’t same as CDN cache. For CDN cached objects, inspect the response header’s age header to determine if cached asset is coming from Cloudflare CDN cache.
Thanks again for the reply. I think we still have a misunderstanding.
First of all after 12 hours I am still getting a response back in Chrome that shows STALE for a resource with max-age of 20 seconds and an age of 42300. That’s the behavior I’m wanting to prevent and perhaps it just isn’t possible. Ironically I got into this rabbit hole because I was trying to implement stale-while-revalidate and couldn’t get it working.
I don’t want STALE content unless I’m setting stale-while-revalidate or stale-if-error.
This is all somewhat of an academic exercise at this point because if my server is up then I’ll get the refreshed content - and if my server is down for any length of time I have bigger problems!
Maybe the answer to my original question is simply:
‘If the origin cannot be contacted then regardless of Edge TTL rules or cache-control your content will be served as STALE indefinitely until Cloudflare purges the cache during routine maintenance.’
Again I am not setting any ‘Edge Cache TTL’ page rules.
Cloudflare will respect your origin expires / cache control headers to calculate the Edge Cache TTL (providing you don’t override it with a page rule setting an explicit Edge Cache TTL).
That’s exactly what I’m seeing. It’s simply not true that the minimum TTL for a Pro plan is 1 hour - that is ONLY a limitation of the dropdown.
I what you’re insisting is actually true then please explain how if I keep refreshing my page on different browsers and different devices that a breakpoint in my code is hit only one time in every 20 second window (and not 1 hour). That means the edge cache is expiring after 20 seconds. The limitations across plans is quite frankly just a marketing ploy.
stale-while-revalidate works on Cloudflare just not strictly to RFC specs. The specs say server MAY serve a stale response on revalidations but it doesn’t say must on every request. What Cloudflare does for stale-while-revalidate is it will only serve a stale asset on revalidation when there are concurrent requests to the same asset and not for non-concurrent requests. So what happens if you as a single request user do a non-concurrent request for an asset that revalidates, you will not get that stale response but either a expired/revalidated one as Cloudflare only will serve that stale asset if there are concurrent requests for that asset.
So if stale-while-revalidate is what you desire, and you can live with stale assets being served only for concurrent requests to that asset, then just set stale-while-revalidate header and be done with it For me that is good enough as you only really need to do that when there’s alot of traffic which maybe of high concurrency in nature. Every other single non-concurrent request can get a revalidated asset.
Yes Cloudflare may expire assets sooner than min Edge Cache TTL if the asset is infrequently accessed from my understanding but what that threshold or criteria is I don’t know. Just be sure you’re testing properly with right request headers (via command line or browser/online tools) i.e. not no-cache etc and testing from same CF datacenter region as CF CDN cache is per datacenter.
The stale-if-error directive is ignored if Always Online is enabled or if an explicit in-protocol directive (e.g., by a *no-store *or no-cache cache directive, a must-revalidate cache-response-directive, or an applicable s-maxage or proxy-revalidate cache-response-directive) is passed.
must-revalidate The must-revalidate response directive indicates that once it has become stale, a cache (client or proxy) must not use the response to satisfy subsequent requests without successful validation on the origin server.
maybe try just cache-control: public,max-age=20,stale-while-revalidate=60 and ensure a page rule for origin cache control is enabled
I’ve done a few more tests and they’ll have to be my last for this round!
First of all when I go directly to my server and not through Argo tunnel it takes 15 seconds rather than 2 to determine that the server is down but it is still willing to return a STALE response - even well after max-age and stale-while-revalidate times have elapsed.
However after a while (maybe an hour) it did eventually decide to give me an error back - which is much less than the 12+ hours I saw with Argo. Still not sure I proved anything with that informal test.
This is what I just tested now regarding revalidation:
Just checked my Cache Analytic stats and can confirm stale-while-revalidate works as I have CF Worker doing guest full page HTML page caching on my blogs and forums and it uses stale-while-revalidate header set to 60 seconds and can see STALE requests served up mainly to my robots.txt file as I guess search bots do have concurrent request traffic patterns