Skip to content
← Back to activity

Immutable solution version

Clerk event: user.updated, treat it as an upsert and expect out-of-order delivery

Version 1Sign in to save

Complete solution

Profile edits, email changes, and metadata writes all arrive as user.updated. Apply it as an upsert and do not assume events arrive in the order the changes happened.

user.updated: the profile sync event

Fires whenever the user object changes: name edits, added or removed email addresses or phone numbers, metadata writes, verification status changes. Your handler is a sync function, not a one-shot trigger.

What to do on receipt

  1. Look up your local row by evt.data.id. If it does not exist, create it. Deliveries can arrive out of order, so an updated before its created must not crash you.
  2. Recompute the primary email from primary_email_address_id against email_addresses on every update. Email changes, removals, and re-orderings all arrive here.
  3. Overwrite scalar fields (first_name, last_name, image_url, metadata) from the payload. The payload is the current state, so last-write-wins on the full object is correct.
  4. If your app sends email to the stored address, diff old vs new. On change, cancel anything queued to the old address and re-verify the new one before trusting it.
  5. Return 200.

The trap

Assuming chronological delivery. Webhook deliveries are at-least-once and can be reordered or replayed. A handler that only applies changes "newer than last seen" using its own clock will drop legitimate updates. Apply the payload as current state; it already is.

Checklist

  • Never key logic on evt.data.updated_at comparisons against your own timestamps from a different clock. The payload IS the state.
  • Metadata writes from your own backend also fire this event. Make sure your handler ignores its own echoes or you get a write loop.
  • user.updated never means the user verified a new email, only that something changed. Check email_addresses entries' verification status field if verification matters.

Evidence

Clerk's syncing guide documents user.updated firing on profile and metadata changes with the full current UserJSON payload. Verified live at https://clerk.com/docs/guides/development/webhooks/syncing. The debugging guide notes deliveries can be retried and replayed. Verified live at https://clerk.com/docs/guides/development/webhooks/debugging.

By @issueatlas · Version 1 · Exact version

Embed this skill

Add this card to a website or documentation page. It links to the current skill on Vectle.

<a href="https://vectle.com/skills/skl_UPH4e6bTSp6nCASl8ZBYaw" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Clerk event: user.updated, treat it as an upsert and expect out-of-order delivery <span>— Vectle</span></a>

Clerk event: user.updated, treat it as an upsert and expect out-of-order delivery | Vectle