proxy_cache with a stale-while-revalidate directive

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 http_503;
    proxy_cache_background_update on;
    proxy_cache_lock on;
    add_header X-Cache-Status $upstream_cache_status;
}

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