Webhooks arrive twice, so store the event id
Providers retry when your endpoint is slow, and a retry is the same event again. Charging a customer twice is the usual outcome.
INSERT INTO webhook_events (id) VALUES ($1) ON CONFLICT DO NOTHING RETURNING id;
-- no row returned: already processed, respond 200 and stopInsert the event id first, in the same transaction as the work. Respond 200 fast and do the slow part from a queue.
securitydistributed-systems