Cookies over HTTP
Control cookie scope and lifetime
Use host-only defaults, narrow paths, Max-Age, and matching deletion attributes instead of creating accidental cookies.
A cookie is not identified by its name alone. The browser identifies it by name, domain, and path together. Get one of those wrong and you’re creating a second cookie instead of updating the first.
Domain
Leave the Domain attribute out. You get a host-only cookie, sent only to the exact host that set it. notes.test sets it, notes.test receives it, app.notes.test never sees it.
Add Domain=notes.test and the cookie now travels to every subdomain too. Sometimes you want that. Most of the time you don’t, and it widens who can read and overwrite the value. My default is to omit it and add it only with a specific reason.
Path
Path limits which URLs receive the cookie. If only the editor at /notes needs a setting, scope it there:
Set-Cookie: editor=compact; Path=/notes; Max-Age=3600; Secure; SameSite=Lax
Requests to /notes and /notes/42 carry it. Requests to / and /help don’t.
Be careful with what Path is for. It controls delivery, not security. JavaScript running on /help can still read a /notes cookie by loading a frame or changing its URL. Same origin is same origin. Never rely on Path to hide a value from other code on your own site.
Lifetime
Max-Age sets the lifetime in seconds. 3600 above means one hour. Expires does the same with an absolute date, but Max-Age wins when both are present and it’s easier to reason about.
A cookie with neither attribute is a session cookie. It should vanish when the browser closes. In practice, browsers that restore your tabs on startup often restore session cookies too. If a value must really be gone, give it an explicit short Max-Age instead.
Deleting the right cookie
To delete a cookie, send it again with Max-Age=0 and the same name, domain, and path:
Set-Cookie: editor=; Path=/notes; Max-Age=0; Secure; SameSite=Lax
This is where the identity rule bites. Suppose you try to delete it with Path=/:
Set-Cookie: editor=; Path=/; Max-Age=0
The browser sees a different cookie, one with path /, and expires that one. The original editor cookie at /notes is untouched. In DevTools you now see it still there, and your logout handler looks broken. The fix is always the same: match the original attributes exactly.
See two cookies with one name
Set editor=compact with Path=/notes and editor=wide with Path=/. Open the Application panel and notice two rows with the same name. Then request /notes and look at the Cookie header. Both travel, and the more specific path comes first.
Now delete each one using its exact path and confirm the row disappears. Then try deleting with the wrong path once, on purpose, so you recognize the symptom next time.
Lesson completed