Skip to content
diff/reel
All reels
Web

Session vs JWT

Session vs JWT — opening frame

sandboxed iframe · 44.5s loop · 26 KB

Made with Diffreel — draw your own →

One keeps the truth on the server, the other hands it to the client and hopes it comes back honest.

By · Posted Aug 15, 2026 · 12 views

Both answer one question — who is this request from? — and keep the answer in a different place.

Server sessions resolve identity with a lookup: the server holds a session record and hands the client an opaque ID. Revocation is instant, because deleting the row deletes the session. The cost is a lookup on every request and somewhere to keep the sessions.

JWTs resolve identity with a signature check: the server signs the claims and hands them over, so no lookup and no shared store. The token is then valid until it expires — and revoking one early means building exactly the lookup the token existed to avoid.

The animation follows one logout through both designs.

Source

Session vs JWT: where the truth about who you are lives

4 min read

A server session keeps the truth about who you are in a store on the server and hands the browser only a meaningless ID that points back to it; a JWT hands the browser the signed truth itself and stores nothing, trusting the signature to prove the claims came back unaltered. That is the difference between server sessions and JWT: whether the proof each request carries is a pointer to server-held truth, or the truth itself, signed. HTTP forgets you between requests, so every request must carry proof of identity — these two designs only disagree on where that proof's meaning lives.

The opaque ID — server sessions

When login succeeds, the server writes a session record — user id, role, whatever else — into a server-side store and sends the browser only an opaque identifier in a Set-Cookie header. The value is deliberately meaningless — OWASP requires the session ID to carry no PII, no role, no username. Something like 9vKx3mQpZ7tR2wLnB4hJ8cYdF6sA1eGu: 32 characters that mean nothing to anyone but the store.

The browser replays that cookie automatically, and on every request the API looks the ID up in the store to get the record back. That second hop is the whole design. It is what makes sessions stateful, and it is what makes logout trivial: req.session.destroy() deletes the record, and the next request presenting that ID resolves to nothing. RFC 7009 describes the stored case exactly — invalidation is immediate, and the identifier cannot be used again.

The signed claims — JWT

A JWT inverts this. Login builds a claims set and signs it; nothing is stored. The browser receives the whole token — three base64url parts separated by dots (RFC 7519 §3), the canonical jwt.io example measuring 155 characters. On each request the API verifies the signature with its key and reads the claims in place. No store, no second hop: a self-contained token lets the resource server decide without ever contacting the issuer.

One trap catches beginners hard. The payload is encoded, not encrypted. Anyone holding the token can paste it into jwt.io and read every claim — which is why jwt.io warns never to put secrets in a payload unless it is separately encrypted. Signing buys integrity, not confidentiality; only JWE buys secrecy.

The JWT revocation problem

Here is the load-bearing difference. A session is revoked by deleting one server-side record. A signed JWT has no server-side record to delete, so it stays valid until its exp claim passes — RFC 7519 §4.1.4 makes exp the only thing that ends it.

This is the JWT revocation problem, and it is confirmed by two sources that do not cite each other. RFC 7009 §5 says immediate revocation of a self-contained token needs non-standardised backend machinery, or short lifetimes instead. OWASP's JWT Cheat Sheet independently arrives at the same workaround: a deny list keyed on the jti claim, held in a shared database. That deny list is a session store wearing a different hat — the exact state a JWT was adopted to remove.

Are JWTs stateless?

So, are JWTs stateless? As issued, yes: the signature is self-verifying and no server remembers the token exists. That is precisely why beginners believe logging out kills a JWT. It does not. "Log out" clears the token from the browser; the token itself stays valid, and accepted, until exp. Anyone who copied it keeps working access. Add the one feature that fixes that — a revocation deny list — plus a per-request user lookup or a device list, and the server-side state is back. Stateless is a property of the token in isolation, not of the system you ship around it.

When to use JWT vs sessions

The answer to when to use JWT vs sessions is really a question about revocation — about who can be un-trusted, and how fast.

  • Reach for server sessions as the default for first-party web apps. You get instant logout, easy "sign out everywhere," and the power to change a user's permissions the moment you decide, all for one store lookup per request.
  • Reach for a JWT when the verifier genuinely cannot phone home: short-lived service-to-service tokens, third-party API access, or a stateless edge that must validate without a shared store. Keep the lifetime short so the window you cannot revoke stays small.
  • The common production answer is the hybrid — a short-lived JWT access token backed by a stateful refresh token. It is a composition of both designs, not a third thing.

Session vs JWT in a system design interview

An interviewer asking "session or JWT?" is probing whether you know that stateless is a trade, not a free win. The crisp answer: sessions put the truth in a server store and hand out an opaque pointer, so revocation is a delete; JWTs put signed truth in the client, so there is nothing to delete and revocation needs extra machinery.

Say what each buys. Sessions cost a lookup per request and buy instant control; JWTs skip the lookup and pay for it at logout. Then name the failure mode before you are asked: logging out does not invalidate a JWT, and the standard fix — a deny list — is server-side state again. Naming the JWT revocation problem unprompted is the signal that separates someone who has run this in production from someone who only heard that "JWT scales better."

Sources

Related reels