Theory

Context picks the answer: revocability vs statelessness

Here is the trap this lesson disarms: the internet is full of "JWT vs sessions — which should you use?" posts that pick a winner. Neither wins. They are optimised for different contexts, and you have now lived in both.

A mobile client has no cookie jar — and talks to an API. Pica is a native app hitting a JSON API. There is no browser automatically attaching a cookie; the app manages its own credential and sets a header explicitly. The API may be several stateless instances behind a load balancer, with no shared session table. In that world a self-contained, signature-verified token is the natural fit: every instance can check it alone, and the client was going to manage and attach the credential by hand anyway. The JWT's statelessness is a feature here.

A server-rendered app has a browser — and a session table. SignFlow renders HTML to a browser, which automatically sends a cookie with every request. There is already a database in the request path (every page reads from it). Adding one indexed session lookup is negligible, and in return the app gets server-authoritative sessions: it can see who is logged in, expire sessions, and revoke instantly. The session cookie's statefulness is a feature here.

The trade, named: revocability vs statelessness. A JWT gives you stateless verification and takes away revocation. A server session gives you revocation and takes away statelessness (it needs a store). You do not get both for free — every design pays one of these costs. The context decides which cost is cheaper:

Pica (mobile → API) SignFlow (browser → server-rendered)
Credential JWT in Authorization header opaque token in HttpOnly cookie
Server state none — verify by signature a sessions row per login
Verification recompute the signature DB lookup by token hash
Revocation impossible (nothing to delete) one DELETE
Sent by the client, explicitly the browser, automatically
Scales to N instances trivially (stateless) needs a shared session store

Read the table as one sentence: the answer changes because the client and the deployment change. This is not a matter of taste or fashion; it is the mechanism matching its environment. You can argue it from experience now, because you shipped both.