Proxy caching

NGINX · Advanced · 14 min

A well-configured cache can absorb most traffic and keep a site up while the backend is struggling.

Proxy caching takes two pieces:

  • proxy_cache_path (in http) defines the storage: a directory, levels for subdirectories, a shared memory keys_zone for metadata (1 MB holds about 8,000 keys), max_size and inactive (remove items not accessed for that long).
  • proxy_cache zone_name; in a server or location enables it.

What gets cached and for how long:

  • By default NGINX respects the backend's Cache-Control, Expires and Set-Cookie headers; responses with Set-Cookie or private/no-store are not cached.
  • proxy_cache_valid 200 301 10m; sets lifetimes when the backend gives none.
  • proxy_cache_key defaults to $scheme$proxy_host$request_uri; add cookies or headers carefully if responses vary by them.
  • Only GET and HEAD are cached by default.

Resilience features:

  • proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; serves expired content when the backend fails.
  • proxy_cache_background_update on; refreshes stale items in the background.
  • proxy_cache_lock on; lets only one request populate a missing item (no stampede).

Add add_header X-Cache-Status $upstream_cache_status; to see MISS, HIT, EXPIRED, STALE or BYPASS while testing.

Example

http {
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=app_cache:10m
                     max_size=1g inactive=60m use_temp_path=off;
    server {
        listen 80;
        location / {
            proxy_pass http://127.0.0.1:8000;
            proxy_cache app_cache;
            proxy_cache_valid 200 301 10m;
            proxy_cache_valid 404 1m;
            proxy_cache_use_stale error timeout updating http_502 http_503;
            proxy_cache_background_update on;
            proxy_cache_lock on;
            proxy_cache_bypass $cookie_session;    # logged-in users skip cache
            proxy_no_cache     $cookie_session;
            add_header X-Cache-Status $upstream_cache_status;
        }
    }
}
# curl -sI localhost/products | grep X-Cache   -> MISS, then HIT

Remember

  • proxy_cache_path defines storage; proxy_cache enables it per location
  • use_stale and background_update keep serving when the backend fails
  • $upstream_cache_status shows HIT, MISS, STALE and more

Watch out for

  • Caching personalised pages under a shared key; bypass the cache for logged-in users or vary the key.

Check yourself

  1. The backend is down but an expired copy exists. Which directive lets NGINX return it?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache