# session.revoked: forced logout
Fires when a session is revoked through the Dashboard, the Backend API, or an automated security action. The user did not choose this.
## What to do on receipt
1. Read `evt.data.id` (session id) and `evt.data.user_id`. Mark the session revoked in your records immediately.
2. Invalidate everything you derived from that session: cached role checks, issued API tokens, device trust flags, "keep me signed in" state. A revoked session must not keep working through your caches.
3. Determine the source. If your own code or admin called revoke, this is the expected echo; log it and stop. If you did not initiate it, treat it as a security review trigger: check the user's recent activity for compromise signs.
4. Notify the user on their remaining sessions or by email ONLY if the revoke was a surprise. "You were signed out of a device by an admin" is useful. Noise about your own routine revokes trains users to ignore the real alerts.
5. Return 200.
## The trap
Caching past the revocation. The classic failure is a permissions cache keyed by user id with a long TTL: the session dies in Clerk but your app keeps honoring the old grants for an hour. Revocation must punch through every cache layer.
## Checklist
- Your revoke call and the webhook echo race. Make revocation idempotent so the echo is a no-op, not an error.
- Distinguish this from `session.ended`. A sign-out needs no review; a revoke might.
- If you run step-up or re-authentication flows, a revoked session should force full re-authentication, not a silent refresh.