← Blog Β· May 19, 2026 Β· dev, security

JWT vs Session Authentication: A Practical Decision Guide

The internet has spent the last decade arguing about JWTs. Stack Overflow has 10,000 questions about them. Most teams reach for them by default. Most teams probably shouldn't. Here's a practical guide to when JWTs are the right call and when traditional sessions win.

The mechanics

Session auth: Server creates a record (session ID + user data) in a database or in-memory store. Returns the session ID to the client as a cookie. On every request, the client sends the cookie; the server looks up the record. To log someone out, delete the record.

JWT auth: Server signs a payload containing the user's identity and any claims. Returns the signed token to the client. On every request, the client sends the token; the server verifies the signature cryptographically β€” no database lookup needed. To log someone out... it's complicated.

Decode a JWT to see what's inside using our JWT decoder. It splits the three base64-encoded parts (header.payload.signature) and shows you the claims.

The case for JWTs

The case against JWTs

Decision tree

Pick sessions if:

Pick JWTs if:

If you do use JWTs: best practices

  1. Short expiry: 15 minutes max. Refresh tokens for longer sessions.
  2. Use HS256 or RS256, never "none". Validate the algorithm explicitly.
  3. Store refresh tokens server-side with the ability to revoke. Yes, this is a session table. That's ok.
  4. Don't put secrets in the payload. JWTs are signed but not encrypted. Decode one and see for yourself β€” try our JWT decoder.
  5. Validate iss, aud, exp on every request, not just the signature.

What about the OAuth2 confusion?

OAuth2 doesn't mandate JWT β€” it's a separate spec. OAuth2 issues access tokens which CAN be JWTs, opaque strings, or other formats. Google issues JWTs. GitHub issues opaque tokens. Both are valid OAuth2.

Tools that help

← All blog posts