I have a problem where signed in users are seeing the signed out version of a page they had previously viewed before signing in. Steps to reproduce:
User visits page A while NOT signed in – correctly sees signed out version with ads
User goes to sign in page and signs in
User re-visits page A and still sees the signed OUT version of the page. If the user hard refreshes the page, the correct signed in version appears
If user visits page C which they had not yet visited signed out, they will see the correct signed IN version of the page without ads.
Environment and setup:
Wordpress site, no caching related plugins installed
Host is Kinsta (Kinsta CDN disabled; Kinsta edge caching disabled)
Full cloudflare integration with DNS managed through cloudflare, Pro account level
Cloudflare APO enabled, no page rules set.
Passing these cache-control headers to signed in users via child functions.php: no-cache, must-revalidate, max-age=0, no-store, private
Passing these cache-control header to signed OUT users: max-age=2592000, must-revalidate, public
The only work-around way to fix this is to pass a Vary Cookie header as well, but that doesn’t seem like a good idea for cache performance as my pages do not vary depending on each user…just whether signed in or signed out.
I was under the impression that Cloudflare APO recognized and handled the signed in vs signed out state (using the wordpress_logged_in_ cookie if I recall correctly). For most people, I understand this ability to differentiate logged in/out works without special configuration.
Any ideas for a solution on this? I’ve been on with kinsta support several times and am not getting anywhere.
As a possible clue to the problem (or maybe not) my Cache Performance dashboard on cloudflare is showing 99% if the html content still being served by the Origin, not cloudflare.
By user, I just mean if I sit down in an incognito browser and perform steps 1-4, or you do the same, etc. (Where would I check if I am restoring original IPs?)
But if I set the one for signed out users to no-cache, then won’t that kill my edge cache hit ratio??
I thought and had read multiple place that cloudflare APO knows to differentiate between signed in and signed out users automatically without other configuration (Brian at perfmatters said he uses cloudflare APO out of the box with kinsta on hundreds of sites and doesn’t have to do anything special to differentiate between signed in and signed out users).
When I used to use Kinsta’s edge caching, it also properly differentiated between signed out and signed in users.
So shouldn’t cloudflare APO handle this anyway (using the wordpress_logged_in_ cookie for example)?
Yes, APO handles this. My point was that browser don’t, so you should not instruct browsers to cache your pages. APO actually ignores your cache-control headers entirely.
So what is the solution do you think? This says APO should already be working since it ignores Cache-Control header and supposedly knows to bypass cache when a cookie starting with wordpress is present.
APO is working, otherwise a forced-refresh would still show the same page. Cloudflare is sending the new (logged-in) page when asked.
Your problem is because the browsers are not even asking Cloudflare for a new page. They have cached the old page and see no reason to ask for anything new unless you force a refresh.
Thank you. I’m trying to understand: I think what I hear you saying is the browsers look at and respect the cache-control headers but that APO ignores them, correct?
So if I set signed-out users’ cache-control header to no-cache also, then that should solve the issue of cloudflare serving a signed out re-visited page to to newly signed in users.
But as a consequence, doesn’t the no-cache directive also mean that a user’s browser cache will never be used and it will have to go to the edge cache for every repeat view?
Cloudflare does not serve signed-out pages to signed-in users. The signed-in users ALREADY have the page in their browser cache from before they signed in.
Yes, that is exactly what it means. The browser can cache 99% of assets (images, css, js…), but not html.
This solution seems to be mostly working, except with regard to pages that have query strings, in which case I seem to always see these headers:
|cf-cache-status|EXPIRED|
|cache-control|max-age=2592000, no-cache, must-revalidate, public|
|vary|Accept-Encoding|
|cf-apo-via|origin,miss|
|cf-edge-cache|cache,platform=wordpress|
I am using a Cache Rule (beta) with a known list of query strings that I use set to “eligible for cache”
Before I added the no-cache to the cache-control header, those pages with query string were showing HIT on the cf-cache-status.
So, is it possible that APO ignores the cache-control header but that Cache Rules (beta) adheres to the cache-control header?
In which case, would the best bet be to override the “eligible for cache” setting for Edge TTL and “override origin” and set it to some number of days?
But then this seems like lots of layers of complexity being added. Is there not a way to just have APO work without having to set the no-cache on cache-control for signed out users? (by “work” I mean not showing the signed out version of pages to signed in users in the 1-4 flow shown in my original question)
Something that may be relevant here: Kinsta, who uses cloudflare integration, originally had this same bug in their version of edge caching. It was fixed June 19th. Here is the note from their support to me:
“We implemented a max-age=0 header rule to force the browser to immediately revalidate the page.” Then “We made a GLOBAL bugfix/improvement on June 19th by adding max-age=0 to the Cache-Control header on Edge Cached pages to avoid the cache issue that you were experiencing with ads showing up for logged-in users.”
When I was using Kinsta edge caching, this fixed the issue for me where the previously viewed signed out version of a page was appearing when the user signed in and went back to that same page.
So perhaps cloudflare would benefit from adding this same max-age=0 to their edge cached pages?
Based on this issue I wonder if getting rid of the Cache-Control no-cache directive on signed out users and adding Vary: Cookie header is the best bet overall in terms of:
-maximizing edge cache hit rate
-ensuring signed in user don’t see signed out versions of pages
Testing and this seems to be working best so far.
I wish APO and/or edge cache settings handled this better out of the box.
If you look at HTTP caching - HTTP | MDN, you’ll see that max-age=0, must-revalidate and no-cache are essentially the same thing.
Generally, it is very hard to debug problems when you don’t have access to the site and only half the necessary information.
Yes, that’s how it works.
Have you thought about whether this is really a good idea? It means that these pages will only update after 30 days for logged-out users, unless you purge Cloudflare’s cache manually.
I don’t know how your site works, but caching html is not a trivial problem.
If you want to do this, you can select Edge-TTL in your Cache Rule and select “Override Origin”.
Let me back up and explain what I’m trying to do big picture.
Before a few days ago, my setup was:
-Kinsta with their cloudflare integration
-Kinsta edge caching and Kinsta CDN both enabled, and Kinsta set a list of 25 query strings that my site uses to also be able to be edge cached.
-I was not sending any Cache-Control headers for signed in nor signed out users
-Cache was working correctly both for pages with and without query strings and signed in user were not seeing signed out versions of pages.
Now, my setup is:
-Kinsta with their cloudflare integration
-Kinsta edge caching and Kinsta CDN both DISABLED
-Cloudflare APO enabled
MY GOAL: All I want is for the same caching behavior I was getting from Kinsta’s edge cache to be cached by Cloudflare’s edge cache. (Caching both for pages with and without query strings, and correct page served to signed in users)
It seems kind of pointless to switch from a Cloudflare setup that works and is free to a paid alternative where you have to configure most things yourself.