How To Disable ETag in NGINX – A Quick Fix for Stale Browser Caches
In a few clicks you can stop NGINX from sending the ETag header that tricks browsers into thinking they already have the latest file. The result? Fresh content on every hit, no more “old picture still showing” complaints.
Why Disable ETag?
ETags are a double‑edged sword.
On one hand, they let browsers avoid re‑downloading files it thinks haven’t changed. On the other, in a world of CDN edge caches and aggressive client caching, they can lock users into an older version until you force a purge or hit a cache‑busting query string.
I once had a corporate intranet where employees kept seeing the old PDF after we updated it. Even though the file size changed, browsers still served the cached copy because of its ETag. Turning off ETags made the browser revalidate every request and resolved the issue in seconds.
Where to Put It
Open your site’s NGINX configuration – usually /etc/nginx/sites-available/default or a file under /etc/nginx/conf.d/.
Add etag off; inside the http block (global) or inside a specific server block if you only want it for one virtual host.
http {
# …other global settings…
etag off;
server {
listen 80;
server_name example.com;
root /var/www/html;
# other server‑specific directives…
}
}
Adding it to the http block disables ETag for all sites on that NGINX instance.
If you’re proxying upstream services, you might also want to strip any ETag coming from them:
proxy_hide_header ETag; add_header ETag "" always;
Testing Your Change
1. Validate the syntax – run sudo nginx -t.
If it reports “syntax is ok” and “test failed”, you’ll see exactly what’s wrong.
2. Reload NGINX – sudo systemctl reload nginx (or nginx -s reload).
No downtime, just a graceful restart.
3. Verify the header – use curl or your browser dev tools:
curl -I http://example.com/index.html | grep ETag
You should see nothing back. If you still see an ETag, double‑check that you edited the right file and reloaded correctly.
Common Pitfalls
- Wrong config file – NGINX may be pulling from /etc/nginx/conf.d/*.conf or a custom include. Use nginx -T | grep etag to find where the setting is applied.
- Cached reverse‑proxy headers – If you’re behind another proxy, its ETag can still reach the client unless you hide it with proxy_hide_header.
- Static vs dynamic content – The etag off; directive only affects static files served directly by NGINX. Dynamic responses (e.g., from PHP or Node) must be handled at the application level.
That’s it—now your browsers will fetch fresh content instead of being stuck in a stale loop.