Every few months the internet rediscovers the JWT vs session debate and everyone picks a tribe. I've shipped both, broken both in a pentest, and landed on the answer that matters more than the token format: rotation, revocation, and scope.
The debate is a distraction
Stateless JWTs scale beautifully — until you need to revoke one. Server sessions revoke instantly — until you're juggling infrastructure across regions. Both models are fine. Both models are terrible when tokens live for 30 days and never rotate.
The middle path I actually ship
- Short-lived access tokens (minutes, not days) + refresh tokens with rotation.
- Refresh tokens stored server-side, revocable per device — logout means logout.
- Reuse detection: if a refresh token is presented twice, kill the whole family. That's a theft signal.
- Session binding on the sensitive routes: password change, email change, billing — re-authenticate there, always.
Logout means logout. If your design can't guarantee that, redesign it.
The part your users will actually notice
Good auth is invisible — until it matters. Re-auth before dangerous actions feels like a bank doing its job. Instant logout on a stolen-device report feels like being taken seriously. None of this requires JWT or sessions specifically. It requires deciding that revocation is a feature, not an afterthought.