proxy_cache with stale-while-revalidate and a lock

A cache that expires and then blocks every waiting request on one slow origin fetch is a cache that makes the worst moment worse.

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=app:64m
                 max_size=2g inactive=60m use_temp_path=off;

location / {
    proxy_cache app;
    proxy_cache_valid 200 10m;
    proxy_cache_use_stale updating error timeout http_500 http_502;
    proxy_cache_background_update on;
    proxy_cache_lock on;
    add_header X-Cache-Status $upstream_cache_status;
}

proxy_cache_lock alone removes the stampede: one request populates the entry and the rest wait for it rather than all hitting the origin. use_stale updating with background_update is better still — the waiting requests get the stale copy immediately and the refresh happens behind them. The status header is what makes any of this verifiable and is worth leaving on permanently.