Skip to content
ExplainerBackend

JWT vs session authentication, which one to pick

Sessions can be revoked; JWTs verify themselves. Watch one request take each path, then pick the trade-off that fits what you are building.

2 min read
JWT vs session authentication, which one to pick, the opening step of the interactive scene

A request arrives with a credential

Every request carries a credential: a session cookie, or a JWT.

Step 1 of 4

Almost every "should I use JWT?" argument is really an argument about one thing: what happens when you need to log someone out right now. Step through the scene above to see where the two approaches actually differ.

What each one actually is

A session is a record the server keeps. The client holds a meaningless id (in a cookie), and the server looks that id up in a store on every request. The state lives on the server.

A JWT is the opposite. The client holds a token that carries its own data and a signature. The server checks the signature and trusts the contents. Nothing is looked up, because the state lives in the token.

// A session cookie is just a key:
Cookie: sid=8f3c...           // the server owns the record

// A JWT carries the data itself:
Authorization: Bearer eyJ...  // header.payload.signature

The trade-off that decides it

Because a session is a record, deleting it revokes access instantly. Because a JWT verifies itself, it stays valid until it expires, no matter what happens on the server. That single difference drives the rest: sessions cost a lookup but give you control; JWTs skip the lookup but make "log out everywhere" hard.

Read the OWASP session management guidance for the security details, then work through the lesson to see the revocation problem play out end to end.

Common questions

Which one is more secure?
Neither by default. A stolen session cookie and a stolen JWT both grant access. The real difference is how quickly you can shut that access off.
Can I revoke a JWT?
Not directly. You either keep the expiry short, or add a deny-list the server checks on each request, which is a store, the very thing JWTs were meant to avoid.
What should I default to?
For a single app with a login, sessions are simpler and revocable. Reach for JWTs when several services must verify a token without sharing one session store.