Auth & Security63 min total · 19 parts
OAuth 2.0 and JWT Explained: What Really Happens When You Click "Sign In"
Part 16 of 19 · ~3 min
Sessions vs. Tokens: Two Different Models
It's worth zooming out for a second and comparing token-based auth directly against the older approach it's often framed as replacing — server-side sessions, which are nowhere near dead and still show up everywhere. Asking "which one wins" is really the wrong question; the honest framing is that each fits a different shape of architecture, and Tasklight is living proof, because it deliberately runs both of them side by side rather than picking one.
| Server-side session | JWT / token-based | |
|---|---|---|
| Where the state lives | Server — the cookie holds only an opaque ID | Entirely in the token — the server verifies, it doesn't look anything up |
| Revocation | Instant — delete the session row | Hard — valid until exp, without extra infrastructure |
| Scaling across servers | Needs a shared session store | Naturally stateless — any server with the verification key can check it |
| Wire size | Small — just an opaque ID | Larger — the full payload rides along on every request |
| Fits | One application, one login | Several independent services verifying identity without a shared database |
Priya's relationship to Tasklight's web app is a server-side session: her browser holds an opaque cookie, and Tasklight's server looks up what it means on every request. tasks-service and billing-service's relationship to that same request is entirely different — they never see Priya's session cookie at all, only the short-lived JWT Tasklight's backend attaches, and they verify it locally with zero database lookup. Look closely at those two rows in the table and there's a pattern worth naming: whatever makes one model good at something is usually the very thing that makes it bad at the other model's strength. Skipping the lookup is what makes a JWT cheap to verify at scale; skipping the lookup is also exactly why there's nothing to delete when you need one gone right now. Tasklight doesn't resolve that tension by picking a winner — it runs the version with instant kill-switch behavior at the one point where instant actually matters, and the version with no lookup everywhere behind it.
It's worth asking why Tasklight didn't just pick one model everywhere, since running both looks like extra complexity from a distance. The honest answer is that a single choice would have been worse in a specific, concrete way for each side. Make Priya's browser session a JWT instead of an opaque cookie, and disabling her account mid-session would leave her with a still-valid credential for up to fifteen minutes — tolerable for an API call, considerably less comfortable for "am I still logged into the app" at the edge, where instant matters more. Make tasks-service check a server-side session table instead of verifying a JWT locally, and every single task-list load turns into a network round trip to whatever holds that table, for every one of Tasklight's backend services, on every request — the exact cost stateless tokens exist to avoid. Two different jobs, two different failure costs, two different tools.