Back to Blog
2026-06-15• 8 min read

Stop Using JWTs for Stateful Sessions

AuthenticationSystem DesignSecurity

The Anti-Pattern

It has become a pervasive trend in modern web development to use JSON Web Tokens (JWTs) as standard session cookies. Developers often reach for JWTs because they are "stateless" and supposedly easier to scale. However, when used for typical user session management in web applications, JWTs introduce significant security and operational overhead.

Why JWTs Fail as Sessions

  • Revocation is Hard: Because JWTs are stateless, you cannot simply "invalidate" a session on the server. If a token is compromised, it remains valid until it expires. To solve this, teams often build a token blocklist—which immediately re-introduces the state they were trying to avoid.
  • Token Size: JWTs can be quite large, especially if they carry numerous claims. Sending a 1KB token on every single HTTP request adds unnecessary overhead compared to a 32-byte opaque session ID.
  • Data Staleness: If user roles or permissions change, the JWT remains unaware until it is refreshed. This can lead to privilege escalation if a user's access is revoked but their token is still active.

The Solution: Opaque Session IDs + Redis

For 99% of standard web applications, a traditional stateful session management system is far superior.

  1. The server generates a cryptographically secure, random Opaque String (e.g., using crypto.randomBytes(32)).
  2. This string is sent to the client and stored in a HttpOnly, Secure, SameSite=Strict cookie.
  3. The server maps this string to the user's session data in an in-memory datastore like Redis.

This approach gives you instantaneous revocation, perfectly fresh data on every request, and minimal payload size over the wire. Save JWTs for what they are actually good for: Server-to-Server authentication and short-lived, single-use delegated authorization (like OAuth2).