TechnicalVerify webhook signatures and make handlers idempotent
Act as a senior backend engineer. Harden every webhook handler in my {{tech_stack}} app. Providers that send us webhooks: {{integrations}}. Before changing anything, list each endpoint, the events it handles and what it changes in the database.
Signatures:
- Verify every request with the provider's signing secret before acting on it. For Stripe, pass the raw request body and the signature header to the official SDK's webhook verifier; a parsed JSON body will fail the check
- For providers that use HMAC, compute it over the raw body and compare with a constant-time comparison
- Reject events older than about 5 minutes to stop replays
- Signing secrets live in server environment variables, one per environment
- Never skip or soften verification to make an error go away. If it fails, find out why: usually a parsed body, the wrong secret for the environment, or a proxy changing the payload
Idempotency:
- Store each event ID in a table with a unique constraint; if it's already there, return 200 and do nothing
- Apply one event's database changes in one transaction
- Events can arrive twice or out of order. For anything stateful, fetch the current object from the provider's API instead of trusting the event's snapshot
- Return a 2xx quickly and move slow work, such as emails, to a queue or background job, so retries don't pile up
Also: log the event ID, type and result, never the full payload with personal or card data; alert when failures repeat; and keep a safe way to replay a failed event.
Write tests for a valid event, a bad signature, an old timestamp, a duplicate and an out-of-order pair, and show me how to send test events with the Stripe CLI or the provider's tool.
Finish with the files changed and anything you assumed.