Skip to content

Comments

Preserve external_id in customer deletion webhooks#9665

Open
pieterbeulque wants to merge 3 commits intomainfrom
claude/fix-webhook-customer-id-RrmGu
Open

Preserve external_id in customer deletion webhooks#9665
pieterbeulque wants to merge 3 commits intomainfrom
claude/fix-webhook-customer-id-RrmGu

Conversation

@pieterbeulque
Copy link
Contributor

@pieterbeulque pieterbeulque commented Feb 21, 2026

📋 Summary

I lost the ticket, but this was reported somewhere in Plain. It makes sense that you want to have access to the external_id from a deleted customer to sync back to your system.

🎯 What

  • Modified customer_webhook() to restore external_id from user_metadata["__external_id"] when processing customer_deleted events
  • Updated customer_event() to fall back to the preserved __external_id value when the database external_id is None

🤔 Why

When a customer is deleted, the external_id is cleared in the database to allow the ID to be recycled for new customers. However, webhook consumers need the original external_id to properly identify which customer was deleted. The __external_id is preserved in user_metadata for this purpose, but wasn't being used in the webhook payload.

🔧 How

  1. In customer_webhook(): Added logic to check if we're processing a customer_deleted event with a None external_id, and if so, restore it from user_metadata
  2. In customer_event(): Added a fallback to use the preserved __external_id when the current external_id is None

Both changes include explanatory comments documenting the ID recycling behavior.

🧪 Testing

  • I have tested these changes locally
  • All existing tests pass (uv run task test for backend, pnpm test for frontend)
  • I have added new tests for new functionality
  • I have run linting and type checking (uv run task lint && uv run task lint_types for backend)

Test Instructions

  1. Create a customer with an external_id
  2. Delete the customer
  3. Verify that the customer_deleted webhook event includes the original external_id in the payload
  4. Verify that system events for deleted customers also include the original external_id

https://claude.ai/code/session_014o3Ar2JdpnY1DSr3TjLh3P

When a customer is deleted, soft_delete() clears external_id from the
DB column (to allow ID recycling) before the async webhook/event jobs
run. As a result, the customer.deleted webhook payload always had
external_id: null.

The original value is already preserved in user_metadata["__external_id"]
for debugging. This fix reads it back in both the customer_webhook and
customer_event tasks when processing customer_deleted events, so the
outgoing payload correctly reflects the external_id the customer had
at the time of deletion.

https://claude.ai/code/session_014o3Ar2JdpnY1DSr3TjLh3P
@vercel
Copy link

vercel bot commented Feb 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
polar Ready Ready Preview, Comment Feb 22, 2026 6:24am
polar-sandbox Ready Ready Preview, Comment Feb 22, 2026 6:24am

Request Review

Verifies that the external_id is correctly restored from user_metadata
in the customer_webhook task when processing customer.deleted events,
covering both the case where external_id was set and where it was not.

https://claude.ai/code/session_014o3Ar2JdpnY1DSr3TjLh3P
@blacksmith-sh

This comment has been minimized.

MagicMock isn't a descriptor so self isn't bound; the recorded args are
(session, redis, event_type, customer), making customer at index 3.

https://claude.ai/code/session_014o3Ar2JdpnY1DSr3TjLh3P
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants