Skip to main content

Serving Stale Cache in Nginx When the Backend Is Down

Nginx · 18.10.2026 · 5 min read
Illustration for “Serving Stale Cache in Nginx When the Backend Is Down”

When the nginx backend stops responding or returns a 502 or 504 error, the harshest result for a visitor is an error page instead of the site. The proxy_cache_use_stale directive lets nginx serve an outdated version of the page from the cache instead of an error in that situation, while the backend recovers. It does not fix the cause of the failure, it only extends the site's life while the failure is being resolved.

What stale means and how it differs from a normal cache

A normal cache in nginx, set up with proxy_cache_valid directives, lives until it expires, and then the request goes to the backend again for a fresh response. If the backend is unavailable at that moment, without extra directives the request simply fails — the cache for that particular response is already stale and is not used automatically.

The base setup of the cache zone and its time-to-live is covered in the article on proxy_cache and fastcgi_cache. proxy_cache_use_stale builds on that setup and tells nginx: under the listed error conditions, serve the stale entry instead of an error code.

Setting up proxy_cache_use_stale

The directive takes a list of conditions under which the stale cache is used: error — the backend is unreachable or dropped the connection, timeout — it did not respond within proxy_read_timeout, updating — the entry is already being updated by another request, plus specific response codes http_500, http_502, http_503, http_504.

The updating condition is especially useful together with proxy_cache_lock: while the first request updates the cache, the rest get the old version of the page instead of waiting in a queue or hitting the backend at the same time. The location where this is added usually already exists in a server block set up as described in the article on configuring Nginx for a site on a VDS.

proxy_cache_path /var/cache/nginx/proxy levels=1:2 keys_zone=proxy_cache:10m max_size=1g inactive=60m use_temp_path=off;

location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_cache proxy_cache;
    proxy_cache_valid 200 10m;
    proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
    proxy_cache_background_update on;
    proxy_cache_lock on;
    add_header X-Cache-Status $upstream_cache_status;
}

proxy_cache_background_update and background refresh

Several directives work together here and are easy to mix up by name.

DirectiveWhat it does
proxy_cache_use_staleallows serving the stale entry on the listed backend errors
proxy_cache_background_updaterefreshes the stale entry in the background while the client gets the old version
proxy_cache_lockkeeps several requests from hitting the backend at the same time for the same entry
inactivethe time after which an unused entry is removed from the cache on disk

If the goal is to diagnose the backend failure itself, rather than read the X-Cache-Status header, the specific causes of 502 and 504 are covered in the article on diagnosing 502 and 504.

Limits: how long the stale copy lives

proxy_cache_use_stale does not extend the entry forever — it is still removed by the inactive directive if nothing requests it. If the backend is down for a long time and there is no traffic to that page, the stale copy can disappear from the cache before the backend recovers.

Content that changes on every request — stock levels in a warehouse, an account balance — should not be served as stale without a clear warning to the user: for such pages it is more reliable not to cache them at all than to show wrong numbers during an outage.

Checklist before enabling stale caching

Before turning on proxy_cache_use_stale in production, it is worth checking the following points.

  • The cache zone and proxy_cache_valid are already set up and tested in normal mode, without backend errors.
  • Static and slowly changing pages have long inactive values set, so the stale copy does not disappear from the cache too quickly.
  • proxy_cache_lock is enabled, so the backend's recovery is not met with a flood of simultaneous requests for the same page.
  • Pages with personal data and current prices are excluded from this cache with proxy_no_cache.
  • Monitoring checks the X-Cache-Status value for STALE separately from HIT, to see when the site is running on old data.

Frequently asked questions

Does the visitor see that they were shown a stale page?

Nginx does not add a visible warning to the page itself — STALE can only be told apart from a normal HIT by the X-Cache-Status header in the response. If a warning to the user matters, it is added at the application level or through a separate banner that checks this header.

What if the backend never responded for this page at all?

If there was no entry in the cache yet, proxy_cache_use_stale will not help — there is nothing to serve. The directive only works with an already existing copy of the response, cached at least once.

Is proxy_cache_background_update needed if proxy_cache_lock is already enabled?

Yes, these are different mechanisms: proxy_cache_lock limits the number of simultaneous requests to the backend, and proxy_cache_background_update decides who refreshes the entry — the current client waiting for a response, or a separate background request, while the rest get the old version without waiting.

Was this article helpful?
← Back to Knowledge Base Ask Support