JWT vs server sessions for multi-tenant apps: when to use each

JWTs scale horizontally without shared session storage but make revocation hard. Server sessions revoke instantly but require shared state. Here's how to choose.

shield

Private: Decoding, analysis, signature verification, and token generation all run in your browser. Nothing is sent to any server, except a JWKS URL you explicitly enter and click Verify on.

At a glance

JWT advantage
Horizontal scale, no shared session DB
JWT weakness
Hard to revoke before exp
Session advantage
Instant revocation, easy to bind
Session weakness
Requires shared state (DB or cache)
Hybrid pattern
Short JWT + long refresh token

JWTs and traditional server-side sessions solve the same problem (carry authenticated state across HTTP requests) with opposite trade-offs. JWTs are stateless: every server can verify a token without consulting a shared store. Server sessions are stateful: the server looks up the session id in a database for every request. Multi-tenant apps usually need a hybrid.

The hybrid pattern most multi-tenant apps land on

Short-lived JWT access tokens (15–60 minutes) for fast distributed verification. Long-lived refresh tokens (days to weeks) stored server-side, in a revocation-capable database. The frontend silently exchanges the refresh token for a new access token before the access token expires.

This gives you near-instant revocation (≤access-token-lifetime) without the per-request DB hit. Logout is "delete the refresh token + clear the access token from the browser". Permission changes propagate within one access-token lifetime.

Frequently asked questions

Can I revoke a JWT before it expires?expand_more
Not without server-side state. The simplest workaround is short JWT lifetimes (15–60 minutes) backed by a refresh token that lives in your database. If a user logs out or has access removed, you mark their refresh token as revoked. The next time their JWT expires, they can't mint a new one — access ends within the JWT lifetime window.
What about a JWT denylist?expand_more
A denylist (cache of revoked jti values, checked on every request) gives you instant revocation but reintroduces the shared-state requirement that made you choose JWTs in the first place. If you need it, fine — but at that point ask whether plain server-side sessions would be simpler.
When does a JWT make sense for multi-tenant apps?expand_more
When your verifiers are distributed across services or platforms (mobile apps, microservices, third-party integrations) and a shared session store would be a coordination headache. The classic case is API access tokens — short-lived JWTs let services accept tokens without coordinating on session state.

Related guides

Related Tools