No revalidation when using stale-while-revalidate

Maxim Dounin mdounin at mdounin.ru
Mon Jul 27 01:42:00 UTC 2020


Hello!

On Fri, Jul 24, 2020 at 03:21:31PM +0200, Adam Volek wrote:

> On 24. 07. 20 4:33, Maxim Dounin wrote:
> > As long as the response returned isn't cacheable (either
> > as specified in the response Cache-Control / Expires
> > headers, or per proxy_cache_valid), nginx won't put
> > the response into cache and will continue serving previously
> > cached response till stale-while-revalidate timeout expires.
> >
> > Most likely "specific status code" in your tests in fact means
> > responses returned by your upstream server without Cache-Control
> > headers, and hence not cached by nginx.
> 
> This is not the case as far as I can tell. In our tests, the upstream server was set up to send these two responses, the 204 first, and then then the 404:
> 
> HTTP/1.1 204 No Content
> Date: Fri, 24 Jul 2020 11:32:33 GMT
> Connection: keep-alive
> cache-control: max-age=5, stale-while-revalidate=10
> 
> HTTP/1.1 404 Not Found
> Date: Fri, 24 Jul 2020 11:32:35 GMT
> Content-Type: text/plain
> Connection: close
> cache-control: max-age=5, stale-while-revalidate=10
> 
> In this scenario, nginx returns fresh 204 for five seconds and then it returns stale 204 for ten seconds even though it's attempting revalidation according
> to access log at the upstream server. If we send the following 410 response instead of 404 however, nginx behaves as we would expect: it returns the fresh
> 204 for five seconds, then it revalidates it almost instantly and starts returning the fresh 410:
> 
> HTTP/1.1 410 Gone
> Date: Fri, 24 Jul 2020 11:41:56 GMT
> Content-Type: text/plain
> Connection: close
> cache-control: max-age=5, stale-while-revalidate=10

You are right, this seems to be an incorrect behaviour of 
stale-while-revalidate / stale-if-error handling.

Internally, stale-if-error (and stale-while-revalidate) currently 
behave as if "proxy_cache_use_stale" was set with all possible 
flags (http://nginx.org/r/proxy_cache_use_stale) when handling 
upstream server responses.  Notably this includes http_403, 
http_404, and http_429 flags, and this causes the effect you 
observe.

This probably should be fixed.

Just in case, the following configuration can be used to reproduce 
the issue within nginx itself:

    proxy_cache_path cache keys_zone=one:1m;

    server {
        listen 8080;

        location / {
            proxy_pass http://127.0.0.1:8081;
            proxy_cache one;
            add_header X-Cache-Status $upstream_cache_status always;
        }
    }

    server {
        listen 8081;

        location / {
            add_header cache-control "max-age=5, stale-while-revalidate=10"
                       always;

            if ($connection = "3") {
                return 204;
            }

            return 404;
        }
    }

-- 
Maxim Dounin
http://mdounin.ru/


More information about the nginx mailing list