1

I've configured Nginx to cache all responses from an upstream server that always returns Cache-Control: public, max-age=1 but nginx seems to cache the response for 2 seconds. How come?

More specifically, my upstream server is a simple Express.js (node) app that returns the current time:

  app.get('/', function (req, res) {
    res.setHeader('Cache-Control', 'public, max-age=1');
    res.send((new Date()).toISOString());
  });

And this is the relevant nginx config:

http {
  proxy_cache_path /data levels=1:2 keys_zone=zuul:10m max_size=10g;
...
  server {
      location / {
          proxy_cache zuul;
          proxy_pass http://zuul;
          proxy_cache_use_stale updating;
          proxy_cache_background_update on;
      }
      listen 0.0.0.0:80 default_server;
  }
}

I then curl http://localhost in a loop and expect to see the response (containing the timestamp as node.js sees it) change every second. Instead of it changes every two seconds. It's as if Nginx is unwilling to cache responses for less than two seconds, not respecting the max-age returned by the upstream.

How can I convince Nginx to cache responses

0

It's probably proxy_cache_use_stale updating, combined with proxy_cache_background_update. The documentation says

proxy_cache_use_stale

Determines in which cases a stale cached response can be used during communication with the proxied server.

The updating parameter permits using a stale cached response if it is currently being updated. This allows minimizing the number of accesses to proxied servers when updating cached data.

proxy_cache_background_update

Allows starting a background subrequest to update an expired cache item, while a stale cached response is returned to the client. Note that it is necessary to allow the usage of a stale cached response when it is being updated.

Looks to me like it's doing exactly what you've told it to do.

Possible Solution

What I suspect you want is

proxy_cache_use_stale off;
proxy_cache_background_update off;
  • Thanks @Tim. But I'm not sure I follow. Why would serving stale content during an update (that takes about 1ms to happen) increase the lag by a whole second? Nginx gets the request a few milliseconds after the max-age (of 1 second) has elapsed, shoots off an update that returns in about 1ms, and then any subsequent call should already see non-stale content, no? Also, should be noted that I'm using state=on intentionally. I need those stale responses while the cache is updated. – Assaf Lavie Oct 23 '17 at 2:35
  • Are you sure it only takes 1ms to make a request, including connection establishment etc? – Tim Oct 23 '17 at 3:28
  • Positive. The request is sent to a local (same host) node.js process that just returns the current timestamp. It's actually less than 1ms. – Assaf Lavie Oct 23 '17 at 6:42
  • Interesting. Well, try disabling those statements as a test. If it doesn't change anything then this answer is incorrect. I won't delete it though, because it could help someone with a slightly different problem in the future. – Tim Oct 23 '17 at 6:51
  • Interesting. It behaves similarly when they are turned off. Cached for 2 seconds, despite max-age=1... – Assaf Lavie Oct 23 '17 at 6:55
0

Disclaimer

This may not be a solution for the OPs problem. I found this topic when looking for an answer to the exact question which is in the title (it's high in google search results). I'm posting this answer because someone may find it useful after finding this topic like me.

Answer

In my case I found directives set to

proxy_cache_valid 200 302 30m;
proxy_ignore_headers Set-Cookie X-Accel-Expires Expires Cache-Control;

and nginx wasn't respecting max-agein the Cache-Control header and everything was cached for half an hour. Those directives were "hidden" in the nginx.conf file instead of vhost configuration so make sure you also check that place. I removed Cache-Control from the second directive and everyting is caching correctly now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.