Skip to main content
← All notes
Building

The Clerk webhook verifies with Svix before it trusts a single field

software

Clerk does not sign its own webhook payloads. It delegates signature verification to Svix, an open-source webhook delivery platform. Every webhook request arrives with three headers — svix-id, svix-timestamp, and svix-signature. The handler reads the raw request body as text, not JSON, because the signature is computed over the exact byte sequence. Parsing to JSON and re-stringifying would change whitespace or key ordering and invalidate the signature. The Svix Webhook constructor takes the shared secret from the CLERK_WEBHOOK_SECRET environment variable. The verify method receives the raw body and the three headers. If the signature does not match — tampered payload, wrong secret, expired timestamp, replay attack — verify throws and the handler returns a 400 before any database logic runs. After verification, the handler branches on event type. user.created has three paths. First it checks whether a client record already exists with that email but without a clerkId — that means I created the record through the admin panel before the client signed up. If so, it links the existing record by writing the Clerk ID onto it and preserving the name I set. Second, if no pre-created record exists, it upserts by clerkId — creating a fresh client or updating an existing one. Third, if a record already has a clerkId and the same email, the upsert updates the name and email in case they changed during signup. The user.updated handler is simpler — it updates the client's email and name from the latest Clerk data. The update query uses spread operators to only write fields that have values, so a missing first name does not overwrite an existing one with an empty string. The catch block on user.updated swallows errors silently because events can arrive out of order — a user.updated might fire before user.created finishes processing, and the client record would not exist yet. One webhook route, two event types, three Svix headers, three signup paths, and every field is trusted only after the cryptographic signature passes.

Comments coming soon

Sign in with TikTok to leave a comment. Coming soon.