JWT vs session-based authentication: what’s the real tradeoff, and when would you pick each?

IBM Security Engineer 1–3 Years Security

Session-based auth stores a session ID in a cookie, with the actual user data kept server-side, so the server can look up, and instantly revoke, that session at any time. A JWT instead packs the user’s claims directly into a signed token the client holds, so the server can verify it without a database lookup, but that speed comes at a cost: the server can’t force it to stop being valid before it naturally expires, since it never has to ask the server again.

Why this tradeoff exists

JWTs are self-contained and stateless by design, which is exactly what makes them attractive for scaling across many servers without a shared session store. But that same self-containment means “logging a user out” or “revoking access” can’t just delete a server-side record, the token is still cryptographically valid until it expires, whether or not the server “remembers” issuing it.

Best practice

Keep JWT expiry short (minutes, not days) and pair it with a separate, longer-lived refresh token that is checked against the server on each renewal, giving you a real revocation point without losing the stateless benefit for the common case. For session-based auth, store sessions in a fast shared store (Redis) so revocation and lookups stay fast even across multiple servers.

Edge case interviewers probe for

How do you immediately revoke a compromised JWT before its natural expiry? Since the token itself can’t be invalidated, you need an explicit denylist (a store of revoked token IDs checked on each request), which reintroduces the server-side lookup you were trying to avoid, meaning “pure stateless JWT” and “instant revocation” are fundamentally in tension.

Common mistake

Choosing JWT purely because it’s newer or “stateless sounds more scalable,” without weighing that it makes logout and permission changes take effect only after expiry (or requires building the very revocation infrastructure JWTs were meant to avoid).

What the interviewer is checking

Whether you understand this as a genuine security tradeoff (revocability versus statelessness), not a matter of picking whichever technology sounds more modern.

A session cookie is like a coat-check ticket: the actual coat (your data) stays with the attendant (the server), who can refuse to hand it back the moment you’re no longer allowed in, even mid-visit. A JWT is like a signed, tamper-proof wristband stamped with your access level and an expiry time: security can check it’s genuine just by looking at it, no need to call anyone, but they can’t magically make an already-issued wristband stop working before its printed expiry time without keeping a separate “banned wristbands” list to check against.

That’s the whole tradeoff: coat-check tickets are slower to check (an extra step) but instantly revocable, wristbands are instantly checkable but can’t be un-issued early without extra bookkeeping.

Why interviewers ask this

Auth strategy choice has real security implications, this question reveals whether a candidate treats “JWT” as a buzzword or understands the actual revocation tradeoff it introduces.

What a strong answer signals

That you know JWTs aren’t a strict upgrade over sessions, and that you have a concrete plan (short expiry, refresh tokens, denylists) for the revocation gap.

Common follow-ups

  • How would you implement instant logout with JWTs?
  • Where should a JWT be stored on the client, and why does that matter for XSS?
  • What’s a refresh token and how is it different from the access token?

Advanced variation

“How would you handle revoking a user’s permissions mid-session with JWTs?” expects recognizing that claims baked into the token (like roles) are stale until the token expires or is checked against a denylist, unlike a session lookup which reflects the change immediately.

A team issued long-lived JWTs (7-day expiry) with no revocation mechanism, and when an employee’s access needed to be pulled immediately after an offboarding, the token remained valid until it naturally expired a week later. Switching to a 15-minute access token paired with a refresh token checked against a server-side store on each renewal meant offboarding could invalidate the refresh token immediately, cutting off renewed access within minutes instead of days.

auth-refresh.js
// Short-lived access token, verified without a DB hit
const accessToken = jwt.sign({ sub: user.id, role: user.role }, SECRET, {
  expiresIn: '15m',
});

// Longer-lived refresh token, checked against the server on every use
async function refresh(refreshToken) {
  const record = await db.refreshTokens.findValid(refreshToken);
  if (!record) throw new Error('revoked or expired');
  return jwt.sign({ sub: record.userId, role: record.role }, SECRET, {
    expiresIn: '15m',
  });
}

// Offboarding: delete the refresh token, access token dies naturally within 15m
async function revokeUser(userId) {
  await db.refreshTokens.deleteAllForUser(userId);
}
Session-based Client Server lookup every reqJWT Client Verify sig no DB Refresh token = revocation point
  1. 1Session auth is instantly revocable because the server holds the authoritative state.
  2. 2A JWT is verified without a server lookup, but can’t be revoked before its expiry on its own.
  3. 3Short access-token expiry plus a checked refresh token gives JWTs a real revocation point.
  4. 4A denylist for revoked JWTs reintroduces the server-side lookup pure statelessness was meant to avoid.
  5. 5Neither approach is strictly better, the choice is a genuine tradeoff between revocability and scalability.