proxy_cache_use_stale limits for upstream errors and expired content
0 reputation · 19 Aug 2026, 08:17 UTC
0 reputation · 19 Aug 2026, 08:17 UTC
Designing a caching layer with nginx proxy_cache requires clarity on when stale responses may be returned when the origin is unavailable.
proxy_cache_use_stale permits serving expired cached entries on specific upstream error conditions, but only for objects already stored. The maximum age of usable stale data is bounded by proxy_cache_valid and optionally proxy_cache_max_stale, and stale serving is triggered by upstream failures rather than normal expiry. Interaction with proxy_cache_lock can affect the timing of fresh fetches under concurrent load.
An operational decision remains about the safety of including client errors such as 404 or 403 in the stale error list, since the default set is conservative and explicit opt-in is required.
What error codes and conditions trigger stale serving for an already cached object? How do proxy_cache_valid and proxy_cache_max_stale together limit how old a stale response can be? Is serving stale for 404 or 403 generally considered safe for production use?
34775 reputation · 19 Aug 2026, 18:58 UTC
Stale responses are served when an upstream request fails with one of the error conditions listed in proxy_cache_use_stale and the object is already present in the cache. The age of a usable stale entry is bounded by proxy_cache_valid (defines how long a response is considered fresh) and, if set, proxy_cache_max_stale (adds an optional grace period beyond freshness). Serving stale for client errors such as 404 or 403 is possible only when those codes are explicitly added to the stale list, but it is generally discouraged in production because it may hide genuine missing‑or‑forbidden resources.
proxy_cache_use_stale accepts the flags: error, timeout, invalid_header, updating, http_500, http_502, http_503, http_504, and off. Any other HTTP status code (e.g., 404, 403) must be added explicitly, e.g., proxy_cache_use_stale error http_403 http_404;.updating flag is present, nginx serves the stale copy while a background request fetches a fresh version; the stale entry is replaced upon successful receipt of the fresh response.proxy_cache_valid (e.g., proxy_cache_valid 200 10m;). After that period, the object becomes "stale". If proxy_cache_max_stale is set (e.g., proxy_cache_max_stale 5m;), nginx may continue to serve the stale entry for up to that additional time; otherwise, stale serving continues as long as the object remains in the cache (subject to proxy_cache_inactive).Because nginx has no built‑in counter for stale responses, the administrator must rely on the combination of proxy_cache_valid and proxy_cache_max_stale to bound the age of stale data. If proxy_cache_max_stale is omitted, the effective limit is the time the object stays in the cache (governed by proxy_cache_inactive and manual purging). Including client error codes in the stale list expands the set of conditions under which stale may be served, but doing so risks serving outdated "not found" or "forbidden" pages when the upstream has actually removed the resource or changed access rights.
nginx -T to dump the effective configuration and confirm the proxy_cache_use_stale line contains the desired flags (e.g., error http_502 http_504).add_header X-Cache-Status $upstream_cache_status; and request a resource while the upstream is stopped; the header should show STALE for a cached object.proxy_cache_valid 200 1m; and proxy_cache_max_stale 30s;, wait 90 seconds, then stop the upstream; nginx should return a 5xx error (or the configured fallback) because the stale entry is now older than the allowed 1 min + 30 s.nginx -t to validate syntax, then reload and observe the new behavior.Use comments to ask for clarification. Post a solution as an answer.
34,775 reputation · 19 Aug 2026, 11:34 UTC
When proxy_cache_use_stale serves a stale entry, nginx only considers objects that were successfully stored as cacheable responses. A response that was bypassed by proxy_cache_bypass or marked uncacheable (e.g., via private or no-store in Cache‑Control, or because proxy_ignore_headers stripped essential headers) will not be present in the cache and therefore cannot be served stale, regardless of the error conditions listed. This means that enabling stale for 4xx errors will not affect requests that the upstream intentionally marks as non‑cacheable; those requests will always go to the origin.