Lesson 16 / 25

Proxy Caching

Cache upstream responses in NGINX and serve stale content during failures.

A cache in front of your app

NGINX can cache upstream responses on disk and in memory, turning it into a fast, local CDN for your application. proxy_cache_path (in the http context) defines where cached files live, a shared memory zone for keys, the maximum size and how long unused items stay (inactive). proxy_cache zone_name; enables caching in a location, and proxy_cache_valid 200 301 10m; sets how long responses are cached when the upstream does not send its own caching headers (NGINX respects Cache-Control and Expires from upstream by default). The cache key defaults to the scheme, host and URI (proxy_cache_key). proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; serves stale content when the upstream fails, and proxy_cache_background_update on; refreshes in the background. proxy_cache_lock on; lets only one request populate a missing item, preventing stampedes. Responses with Set-Cookie are not cached by default; never cache personalised pages in a shared cache. Expose $upstream_cache_status (HIT, MISS, EXPIRED, STALE) in a header or log while tuning.

Cache between clients and the app

Hits are served from the cache; misses go to the application and are stored for next time.

Client arrows into a proxy box containing a small storage cylinder; some arrows return immediately, a few continue to an application box.
Figure 6.1 — NGINX proxy cache serving hits and filling misses.

Micro-caching an API and serving stale on errors

A one-second cache can absorb huge traffic spikes.

proxy_cache_path /var/cache/nginx/api levels=1:2 keys_zone=api_cache:50m
                 max_size=2g inactive=10m use_temp_path=off;

server {
    location /api/products/ {
        proxy_pass http://api_backend;
        proxy_cache api_cache;
        proxy_cache_valid 200 1s;                       # micro-cache
        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 always;
    }

    location /api/account/ {
        proxy_pass http://api_backend;
        proxy_no_cache 1;                              # personalised: never cache
        proxy_cache_bypass 1;
    }
}

Personalised responses must bypass the cache

If a response depends on the logged-in user and the cache key does not include something that identifies them, one user's data can be shown to another. Bypass caching for authenticated routes unless you are certain of the key.

Quick check: Which directive lets NGINX keep serving cached content when the upstream returns 502 errors?

  • proxy_cache_lock
  • proxy_buffering
  • proxy_cache_use_stale
  • proxy_set_header
Answer

proxy_cache_use_stale — proxy_cache_use_stale specifies conditions under which stale cached content may be served.