Etags: Needle-in-a-haystack problem

June 13, 2025

2 mins read

TLDR:

If you are using response headers for your data, please check your server caching (Etags, Cache-Control, Expires, etc.). Disable them if you must.

Session handling has always been my focus since I started working as a developer. While, I do build on top of an authentication solution, problems still occur that seems impossible at first but actually it is so small and easy to fix that it felt like you've discovered fire in 21st century.

I stumbled on a problem where my cookies weren't updated even after it expired. The authentication solution that I have should automatically contact the server and fetch a new cookie value, but it wasn't able to do so. I've been checking all the debug logs, the headers sent that correlates with the cookie value, my functions that touches the session; yet none has issues until I saw a single comment on a site that mentioned about server caching, and etags.

🪡 Etags - the needle

ETag is a small code (hash) that represents the data sent by the server. When the browser asks for data again, it says: "I already have this code. Do you have anything new?". The server checks. If it’s still the same, it saves time and doesn’t resend everything. Just replies, "Nothing changed."

You could say that this is helpful, why can it be the cause of my cookie issue? 🤔💭

Well, Express has it enabled by default, but their current implementation only checks the response body, and not the response headers for changes. My authentication solution's flow in session handling has to go through the header, and that my friend is where the problem occured. Etag skipped the usual flow of updating the cookies, by just telling the browser that "Nothing changed", even though the headers has been updated.

🙃 Solution

The simpliest solution ever, disable Etags.

app.set("etag", false);

or the other caching solutions (just to make sure)

res.setHeader('Surrogate-Control', 'no-store'); 
res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); 
res.setHeader('Pragma', 'no-cache'); 
res.setHeader('Expires', '0');

📄Final Note

ETags are useful especially for assets, but if you are trying to pass data especially with the use of response headers, it is better to check if your technology supports such as well.

It took me 4-5 hours to find this, and hopefully someone won't spend as much 😂

© 2025 Alec Blance

Bacolod, PH