Session gaps don't lock you out

When the session token doesn't carry the account, the server looks it up once, caches it briefly and injects it — instead of failing every request or hammering the auth provider.

What it is

A rescue path in middleware for signed-in users whose session token lacks the metadata that names their account. It fetches the user once from the identity provider, caches the result per user for sixty seconds in the running instance, and injects the resolved account into the request headers so downstream routes don't each re-derive it.

Also called: no organization error · 403 storm · rate limited by auth provider · session missing org

See it
Session gaps don't lock you out
🔒ridgelinepostframe.com/project/jwt-sp775
Riding Arena
Framing · on schedule
A latency/rate-limit comparison chart: requests per page load hitting the identity provider before and after the cache. Source: src/middleware.ts. Sample data — no customer information appears here.
How it works
  1. 1Runs only when a user looks like they need onboarding and isn't already on an allowlisted route, so the normal path costs nothing.
  2. 2Cached per user id for sixty seconds, per instance; a cache miss re-fetches independently.
  3. 3A resolved account is injected as x-org-id unless the subdomain already supplied one, which takes precedence.
  4. 4A network failure keeps existing behaviour rather than escalating.
  5. 5The server auth layer keeps its own sixty-second cache of the full user fetch for the same reason.
Why we built it

The comment names the cause and the consequence: the default session token 'does NOT include public_metadata or primary_email_address — that requires a custom JWT template most apps haven't set up. Without it, EVERY API request from an apex-signed-in user re-checks Clerk Backend API for org context, and on Clerk dev keys (tight rate limits) we'd 429 within ~20 calls and start returning false-negatives → 403 storm across /api/db, /api/smartbuild, /api/users.' A single page load 'fires dozens of API calls through middleware, blowing the budget within seconds.' The TTL is chosen so onboarding self-corrects: 'after onboarding the user's next request beyond 60s picks up their new orgId.'

The problem
  • Sparse session tokens forced a provider call on every request.
  • Provider rate limits turned into false negatives and app-wide 403s.
  • Each downstream route re-derived the same account context.
Sound familiar?
What you get
Signed-in users aren't told they have no account.
The identity provider is called once per user per minute, not once per request.
Newly onboarded users pick up their account within a minute.

See it on your own jobs

Twenty minutes, your numbers, no slide deck. We’ll build one of your real buildings in front of you and send you the estimate link at the end — yours to keep either way.

or keep browsing features →