Cache-Control headers ignored - CF-Cache-Status = EXPIRED

I don’t believe the origin’s max-age is being recognized by Cloudflare’s cache, consider these page rules:

And, these tests:

# this is kind of what i'd expect: the first is expired, and subsequent requests hit

$ for i in `seq 5`; do curl -s -X GET -I | grep cf-cache ; done
cf-cache-status: EXPIRED
cf-cache-status: HIT
cf-cache-status: HIT
cf-cache-status: HIT
cf-cache-status: HIT

# but if i have sleep 10 in here it is always expired

$ for i in `seq 5`; do curl -s -X GET -I | grep cf-cache;  sleep 10 ; done
cf-cache-status: EXPIRED
cf-cache-status: EXPIRED
cf-cache-status: EXPIRED
cf-cache-status: EXPIRED
cf-cache-status: EXPIRED

I can turn on Edge Cache TTL, and that gives me the expected behavior, but I’d rather let the origin drive the expiration via the cache control header.

What is going on here?

My theory is that without Edge Cache TTL, there’s no Age: header, so it’s effectively an Age of 0. And with 5 curls in rapid succession, it’s less than 1. But if you delay a bit, that resource has been purged at the one second mark.

I dunno…caching stumps me at times. But I’m willing to bet it’s the lack of an Age header. Yes, I see there’s an Expires header…still a mystery to me.

Maybe @GulshanKumar is around. He’s really good with cache settings.

1 Like

Thanks @sdayman. I wasn’t familiar with that header - - but it looks like it should be calculated by the proxy. I don’t see mention that I should be setting it in the docs.

I’ll try changing some settings, but will likely make a support ticket. Either way, I’ll reply back with what I find.

Okay, this is embarrassing. Support pointed out my origin had a max-age of 1, which I somehow got confused with our production’s settings which are different.

This was confirmed by:

curl -s -X GET -I --connect-to ::x.x.x.x

I’ll go back in my hole now.


Happens to the best of us. Fortunately they’re quite good at spotting such things.

Happy New year 2020.

Please try these two steps

  • At Page rule, Set origin cache control: on
  • Add a HTTP header response from your Origin side to your Document page

An example, if I wish to cache something in browser for 2 mins (Not taking risk) and caching at CF confidently for 30 days.

Cache-Control: public, max-age=120, s-maxage=2592000

This should work.


Thanks for the suggestions. I’ve been experimenting with those, but my browser isn’t caching “older” responses.

So…let’s say s-maxage is one week, but max-age is one day. Cloudflare cache will hold it for a week, and after a few days, the “age” header will be…3 days (but in seconds). The browser sees it’s older than one day and won’t cache it. Correct?

IGNORE: Is the only way to get a browser to keep it cached regardless of the “Age” header would be to use an Expires header? (Access +1 Day) (nevermind…it just timestamps an expiration that’s an equivalent to cache-control)

I’d suggest you edit the above msg to remove the origin server IP address. This is a public forum, accessible to bots and whatnots.

Good suggestion. This a public origin anyway, but it has since changed.

I realized that what was throwing me - I was getting a different max age at the edge vs. from the origin.

Cache-Control: public, max-age=14400

despite the origin being

Cache-Control: public, max-age=1

This is due to Cache-Control header being overridden by Cloudflare

I’m using workers CF object to drive the cache now, instead of page rules. But, this global setting probably would have highlighted the issue right away:

This topic was automatically closed after 30 days. New replies are no longer allowed.