Build the mental model
HTTP is stateless - each request has no built-in memory of the one before it. Cookies and sessions exist to close that gap.
A cookie is small data a server asks the browser to store - useful for session IDs, preferences, analytics, or security checks. Not every cookie is a tracking cookie.
- Secure - only sent over HTTPS
- HttpOnly - not readable by JavaScript
- SameSite - restricts cross-site sending
- Expires - how long the browser keeps it
A session is server-side state; the browser holds a session cookie containing just an ID, and the server looks that ID up in a session store.
| Aspect | Cookie vs Session |
|---|---|
| Where the data lives | Cookie: stored in the browser. Session: stored on the server, referenced by an ID. |
| What the browser holds | Cookie: the actual data (or an ID). Session: only a session ID; the real state stays server-side. |
| Typical size limit | Cookie: a few KB per cookie. Session: as large as the server-side store allows. |
| Revocation | Cookie: cleared by browser or expiry. Session: can be invalidated instantly by the server. |
- Cookie
- A small piece of data a server asks the browser to store and send back on future requests to the same site.
- Session
- Server-side state tied to a particular user, typically referenced by an ID stored in a session cookie.
SESSION MODEL
-------------
SESSION MODEL
--------------
Browser Server Session Store
-------- ------ -------------
Cookie: sid=abc123 -> receives sid -> looks up "abc123"
-> finds: Alice, cart: 3
The cookie itself holds only an ID.
The real user state lives in the session store on the server.Connect it to a real scenario
Check a site's cookies in developer tools - a session cookie is usually there. The browser sends it automatically on every request.
The code below simulates a tiny in-memory session store: it checks whether a cookie ID already exists and decides existing vs new session.
Try the working example
function createSessionSimulator() {
const store = new Map();
let nextId = 1;
return function handleRequest(cookieId) {
if (cookieId && store.has(cookieId)) {
return { status: "existing session", sessionId: cookieId };
}
const newId = "sess_" + nextId++;
store.set(newId, { createdAt: nextId });
return { status: "new session", sessionId: newId };
};
}
const handleRequest = createSessionSimulator();
const incoming = [undefined, undefined, "sess_1", undefined, "sess_1", "sess_2"];
incoming.forEach((cookieId, i) => {
console.log(`Request ${i + 1} (cookie: ${cookieId ?? "none"}) ->`, handleRequest(cookieId));
});Logs six results in order: two new sessions (sess_1, sess_2), a repeat of sess_1 as existing, a third new session (sess_3), then sess_1 and sess_2 again as existing.5-minute try-it
Modify the incoming request list in the code to add a request with a cookie ID that was never issued, and predict whether it's treated as new or existing before running it.
One important caution
Assuming every cookie is a tracking cookie - many are essential to basic functionality like staying logged in.
Forgetting that a session cookie is usually just a reference - losing or clearing it can end a session without deleting any real data.
MDN Web Docs - Using HTTP cookies — How the Web Works