Choosing an identity model
Three models, each seen on its own. Put them next to each other and what they're optimising for becomes clear, because each one gives something up to get it.
What each one is really buying
- Stateful sessions anchor everything on the server. Identity lives there and so does control, so they're predictable, updatable and instantly revocable. In exchange you get a central thing that has to scale and stay in sync, which gets harder with every server you add.
- Opaque bearer tokens point at the server. Identity still lives there, in a small token-to-user mapping instead of a full session store. The server gets much lighter without becoming free, since there's still a lookup. A practical halfway house.
- JWTs take the stateless idea to its conclusion, putting the whole identity inside the token. No lookup, no shared store, no coordination, no server load. A signed object the server trusts instantly, and a real fight when you need to revoke access.
- Delegated identity moves the responsibility outside your system entirely. You stop worrying about passwords, and you inherit the complexity of a relationship with a provider you have to get right.
Stateful is for control. Stateless is for scale. Delegated is for offloading trust.
Which is oddly freeing: the question stops being "what's the right answer" and becomes "what can this app afford to be bad at".
Side by side
| Stateful | Opaque token | JWT | Delegated | |
|---|---|---|---|---|
| Identity lives | On the server | On the server, thinly | In the token | With the provider |
| Per request | Session lookup | Token lookup | Signature check | Depends on what you issue after |
| Server storage | Full session store | Small mapping | None | None |
| Revoke now | Yes | Yes | No | Partly theirs |
| Scales sideways | Needs a shared store | Needs a shared store | Freely | Freely |
| You give up | Coordination | Some coordination | Changing your mind | Control |
If you need someone gone right now, the answer is a lookup somewhere. Everything else follows from that.
When each one fits
- Stateful shines when the server has to stay in charge: instant logout, live role updates, tight control over user state. Stable and predictable, and it suits dashboards, admin tools and anything where control matters more than horizontal scale.
- Stateless shines when the architecture needs room to stretch. For an API, or anything scaling without coordinated session state, having the client bring its own token removes that friction immediately. Opaque tokens keep it simple; JWTs remove the lookup entirely.
- Delegated makes sense the moment you realise you don't want to run a password system at all. Or when onboarding speed matters, or when you want a stronger baseline than you'd build yourself. Your app shifts from proving identity to consuming it.
And the shift worth ending on: you often don't pick one. Real systems combine them, using delegated identity to establish who someone is, a session for the main website, and JWTs for API calls. Each solves a different slice of the problem.
Google proves who you are, a session keeps you logged into the site, a token gets you through the API. Three jobs, three tools.
Try it
Five systems. Pick a model for each and name the property that decides it.
- A classic web dashboard for internal staff. Admins need instant logout, permission changes should apply immediately, and security matters more than scale.
- A public API serving a mobile app.
- A large microservice architecture where a dozen services each need to know who is calling.
- A consumer app whose whole goal is fast signup, ideally with Google or Apple.
- A single-server hobby project.
Compare your answers
| # | Model | The deciding property |
|---|---|---|
| 1 | Stateful | The server stays in charge. Change a role or log someone out and it takes effect on the next request. For a normal browser app, sessions are simple and reliable |
| 2 | Stateless, either kind | Each request brings a token the server checks and moves on, with no growing pile of sessions to track as usage climbs |
| 3 | Stateless, specifically JWTs | Self-contained, so each service verifies for itself instead of every service asking a central server on every call |
| 4 | Delegated | No passwords to handle at all, and the fastest possible signup |
| 5 | Stateful | Simplest thing that works. One server, a small session table, one cookie. No tokens, no OAuth, nothing to operate |
One and five reach the same answer from opposite directions, which is the useful part. One picks sessions because control matters most; five picks them because nothing else is needed. Neither is a scaling decision, and scaling is what people assume drives this choice.
Where this goes next
Four questions now travel with you into any login system you meet. Where does identity actually live? How does the server know this person is who they claim? What happens if this leaks, expires or gets tampered with? Which model fits this app, and why?
That's the reasoning, not a checklist, and it's what makes an unfamiliar auth system readable.
The next section changes subject entirely. Rate limiting basics stops asking who someone is and starts asking how often they're allowed to ask.

