Roots Discourse

Caching not working correctly - fastcgi-cache header set to STALE

Hey all,

Interesting problem here. I changed a post from published to private and waited an hour and the post was still showing for logged out users. I checked the headers and instead of seeing HIT, MISS or BYPass, I am seeing STALE.

I hard refreshed, purged browser cache and am still see STALE as the value and the page is still showing.

I then put cache to false in my group var files and all was well… changed it back to true and refreshed and could see the page again.

This seems to be happening to all my sites actually. STALE keeps showing up for posts.

Any idea what is wrong here? Using Trellis 1.2.0: October 11th, 2019

Thanks!

1 Like

I have ran into an issue where using fastcgi_cache_use_stale with fastcgi_cache_background_update can cause issues with 404 pages. If you ever delete a page that has been cached, nginx will keep serving the cached page even if your origin server responds with 404.

It’s because WordPress adds Cache-Control: no-cache, must-revalidate, max-age=0 and expires: Wed, 11 Jan 1984 05:00:00 GMT to 404 pages which nginx will refuse to cache.

That’s why you should use any value in fastcgi_cache_valid and always use fastcgi_ignore_headers Cache-Control Expires . This way your deleted pages will properly return 404 error code. I have updated the code samples to reflect this.

https://siipo.la/blog/never-miss-the-cache-with-nginx-microcaching

What is your fastcgi_cache_valid?

My guess is:
Nginx refuses to update the cache because private pages have Cache-Control: no-cache header. Thus, the old caches (the published version) are used.

In my nginx.conf.j2 file it has:
fastcgi_cache_valid {{ item.value.cache.duration | default(nginx_cache_duration) }};
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;

wordpress role main.yml file has:
nginx_cache_duration: 30s

I don’t change these values in my wordpress_sites file. 30s seems to be the default that comes with Trellis. Should I add a duration:any to my group_vars file?

Thanks!

Ok, I added
duration:any 30s
This seems to have worked and from reading up, this shouldn’t cause any other issues.

Maybe this should be added to the default trellis setup as if not, private posts will never go private if cache is turned on.

Thanks @TangRufus!

2 Likes

I have the same issue! An old page content is served by nginx, no restarting of nginx, php7.3-fpm or even a server reboot helps to force nginx to serve the new page content. This only occurs for non-logged in users, the HTTP header fastcgi-cache: STALE is sent. Apparently the cache is always disabled (fastcgi-cache: BYPASS) for logged in users, hence logged in users can see the new correct page content. This seems to be a Trellis bug.

Interestingly even purging the nginx cache directory didn’t fix the issue, nginx seems to use different or additional caching directories than expected.

Edit: So in my case this had been caused by TablePress (transient) caching. A plugin that changes the TablePress markup was updated, but the old table markup still cached as transient by TablePress.