NGINX Reverse‑Proxy Caching: How to Store, Serve, and Purge Upstream Responses
NGINX’s proxy_cache turns the reverse proxy into a disk‑backed cache. Learn how to define the cache zone, control TTLs, verify hits, and manage disk space and purging in this practical guide.
15 Jul 2026, 20:36 UTC

Problem: Speeding Up Repetitive API Calls
Modern web apps often hit the same backend endpoint repeatedly—think weather look‑ups, product listings, or image thumbnails. Each request forces the upstream server to recompute the same data, adding latency and load. The question is: can NGINX keep a copy of the response and serve it for subsequent requests?
Thesis: NGINX’s proxy_cache lets you turn the reverse proxy into a lightweight, disk‑backed cache that is easy to configure, but you must size it correctly and keep it coherent across instances.
How the Cache Works
NGINX stores cached responses in a shared memory zone defined by proxy_cache_path. Each cached file is named by a hash of the request’s key, which defaults to the scheme, host, and URI but can be customized with proxy_cache_key. When a client requests a URL, NGINX checks the cache:
- Hit – the file exists and is still fresh; NGINX streams it back.
- Miss – no file or TTL expired; NGINX forwards the request to the upstream and stores the response if it is cacheable.
The freshness of a cached item is controlled by proxy_cache_valid, which maps HTTP status codes to time‑to‑live (TTL) values. For example, a 200 response can live 60 seconds, while a 404 might live only 30 seconds.
Concrete Example
# /etc/nginx/conf.d/cache.conf
# 1. Define a cache zone – 100 MB, 10 GB max, stored on disk
proxy_cache_path /var/cache/nginx/my_cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;
# 2. Apply the cache to a location
server {
listen 80;
server_name api.example.com;
location /data {
proxy_pass http://backend.internal;
proxy_set_header Host $host;
proxy_cache my_cache; # enable caching
proxy_cache_valid 200 60s; # 200 OK cached for 60 s
proxy_cache_use_stale error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_cache_key $scheme$proxy_host$uri; # explicit key
add_header X-Cache-Status $upstream_cache_status;
}
}
What to run: As root, create the cache directory:
mkdir -p /var/cache/nginx/my_cache
chown nginx:nginx /var/cache/nginx/my_cache
Then reload NGINX:
nginx -s reload
Test with curl -I:
curl -I http://api.example.com/data/item/42
The first request should return X-Cache-Status: MISS. Subsequent requests within 60 seconds will return X-Cache-Status: HIT. If you delete the cached file manually (e.g., rm /var/cache/nginx/my_cache/…), the next request will again be a miss.
Trade‑Offs and Limitations
- Disk Space – The cache lives on disk; a large
max_sizecan fill the partition. Monitor withdu -sh /var/cache/nginx/my_cacheand rotate or purge when approaching limits. - Multi‑Instance Consistency – If you run several NGINX workers behind a load balancer, each must share the same cache directory. On separate machines, you need a shared filesystem or a distributed cache (Redis, Memcached) instead.
- Purging Complexity – NGINX ships a
proxy_cache_purgemodule that can delete specific keys, but it requires compiling the module or using a third‑party patch. Without it, you must manually delete files or rely on TTL expiry. - Non‑Cacheable Responses – Headers like
Cache-Control: no-cacheor status codes 304/403 are ignored by the cache; NGINX will always fetch fresh data for those. - Stale‑While‑Revalidate – The
proxy_cache_use_staledirective can serve stale content while the upstream is recalculating, improving perceived uptime but potentially returning outdated data.
Practical Checklist
- Define
proxy_cache_pathwith an appropriatemax_sizeandinactivetimeout. - Enable
proxy_cacheon the desired location and setproxy_cache_validfor the status codes you want to keep. - Add a diagnostic header (e.g.,
X-Cache-Status) to verify hits/misses. - Monitor disk usage and
nginx -tafter changes. - For purging, either install
proxy_cache_purgeor manually delete files; consider a script that cleans up by key.
Conclusion
NGINX’s built‑in reverse‑proxy cache is a powerful, zero‑dependency solution for reducing upstream load and latency. By carefully sizing the cache, monitoring usage, and planning for purging and multi‑instance coherence, you can keep the cache healthy and your users happy.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.