Answer
Nginx replaces the stale cache entry as soon as the background subrequest initiated by proxy_cache_background_update completes, regardless of the original TTL of the stale object.
Likely explanation
When a request finds a stale entry that matches proxy_cache_use_stale, nginx immediately serves that stale response to the client and spawns a subrequest to refresh the object from the upstream server. The background update runs independently; once the subrequest finishes successfully, nginx writes the new data over the existing cache file, overwriting the stale entry.
Confirmed facts
- The background update occurs after the stale response has been transmitted to the client (see nginx source:
ngx_http_file_cache_background_update).
- The update uses the same request line and headers (minus those hidden by
proxy_hide_header) and does not affect the response time of the original request.
- While the entry remains stale, nginx performs at most one background refresh per key, preventing repeated fetches for the same object.
- The directive is available from nginx 1.11.10; older versions block the client while updating the cache.
Steps needed for this case
- Define a shared cache zone, e.g.:
proxy_cache_path /var/nginx/cache levels=1:2 keys_zone=STATIC:10m max_size=1g inactive=60m use_temp_path=off;
- In the relevant
location block, enable stale serving and background update:
proxy_cache STATIC;
proxy_cache_use_stale updating error timeout http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on; # optional, to prevent concurrent background updates
- Reload nginx:
nginx -s reload.
- Verify behavior (see verification section).
Verification
- Enable debug logging (
error_log /var/log/nginx/error.log debug;) and look for lines containing "background update" after a request that serves a stale entry.
- Check the cached file’s modification timestamp (
stat) before and after a request: the timestamp stays unchanged during the client response and changes only after the background subrequest finishes.
- Using
curl -I, fetch the same URL twice in quick succession; the first reply shows a non‑zero Age header (stale), the second reply shows a lower Age if the background update completed.
Missing diagnostic detail
No additional diagnostic detail is required to change the recommendation; the described behavior holds for all supported nginx versions when proxy_cache_background_update is enabled.