The honest middle ground — the hybrid moves the trade
Real systems often want both — the scale of stateless verification and the safety of revocation. So they build a hybrid, and the honest thing to notice is what the hybrid actually costs.
Short-lived access token + long-lived refresh token. The common production pattern:
- An access token (a JWT) that lives minutes. It is verified statelessly, exactly like Pica's, and attached to every API call. Because it expires so fast, a stolen one is useful only briefly.
- A refresh token that lives weeks, kept server-side (in a table) and exchanged for a fresh access token when the old one expires.
Now you can "revoke": delete the refresh token. The stolen access token still works — but only until it expires, minutes later, and it can never be refreshed. You have bounded the damage without a database lookup on every request.
But look at what just happened. To get revocation back, the hybrid reintroduced server-side state — the refresh-token table — which is exactly the thing the JWT was supposed to let you avoid. It didn't escape the trade; it moved it: stateless on the hot path (every API call), stateful on the cold path (the occasional refresh). That is a genuinely good engineering choice — it puts the cost where it is cheapest — but it is not a free lunch. The revocability-vs-statelessness trade never disappears. It only relocates.
Which is the real lesson, and the reason you built two whole applications instead of reading one blog post: there is no universal answer, only an answer for a context, and a cost you can name. A mobile app talking to a horizontally-scaled API leans stateless and accepts weak revocation (or adds refresh tokens to claw some back). A server-rendered app with a database in the loop takes server sessions and instant revocation for the price of a lookup it was already paying.
This lesson only exists because both apps exist. If the curriculum had built only Pica, "just use sessions" would be words. If it had built only SignFlow, "just use a JWT" would be words. You built both, hit the wall each one hits, and can now choose — and defend the choice — for whatever you build next.