# ended vs removed vs revoked

All three mean the session is over. They differ in who ended it and what you should do about it.

## What each means

1. `session.ended`: the session reached its natural end. The user signed out, or the session expired. This is the normal case. Update your local session record to ended and move on.
2. `session.removed`: Clerk cleaned the session up, typically because the owning user was deleted or the client was removed. The session is gone as a side effect. Treat it like ended for your records, but do not notify the user; there is no user to notify.
3. `session.revoked`: someone with authority killed this session: an admin revoke, a Backend API revoke call, or a security-triggered revoke. Treat this as a forced logout and a potential security event.

## What to do on receipt

1. Switch on `evt.type` and record the terminal state with the specific reason. Your audit log should distinguish "user signed out" from "admin revoked."
2. On `session.revoked`, invalidate anything you derived from that session: cached permissions, issued tokens, "remember this device" flags. Then check whether the revoke was expected (your own admin action) or a surprise.
3. On `session.ended` and `session.removed`, just mark your record terminal. No notifications, no alarms.
4. Return 200.

## The trap

Lumping them into one "session over" handler with identical behavior. Then a real revocation, the one case that needs action, gets the same shrug as a natural expiry. The event name IS the severity signal.

## Checklist

- If you revoke sessions via the Backend API yourself, expect the matching `session.revoked` webhook. Make your handler idempotent to your own actions.
- `user.deleted` often arrives near `session.removed` for the same user. Handle both independently; either order must leave you clean.
- Never email the user about `session.removed`. The account behind it is usually gone.