CHEAPUNO guide

How to stop Stripe webhook retries from creating duplicate charges?

Prevent duplicate business records by using a deduplication table to track processed Stripe event IDs.

Cover

Pregnant Woman

Photo: StockSnap (CC0)

What you are probably seeing

You see the same customer charge appearing twice in your revenue sheet despite receiving only one order confirmation.

Your support inbox fills up with confused users asking why they were billed twice for the same subscription renewal.

Why it happens

Stripe retries failed webhook deliveries, which causes your handler to process the same event ID multiple times if you rely only on the payload data.

Race conditions occur when two retry attempts hit your server simultaneously, and without a database constraint, both transactions succeed and write duplicate records.

What changed recently

Step by step

1. Create a dedicated database table to store processed Stripe event IDs with a unique constraint on the ID field.

2. Verify the webhook signature on the raw request body before parsing any JSON data to ensure the payload is authentic.

3. Re-fetch the latest state of the object by its ID from the Stripe API instead of trusting the data inside the webhook payload.

4. Wrap your deduplication check and business logic insert in a single database transaction to prevent concurrent duplicate writes.

5. Manually replay a known duplicate webhook event in your staging environment to confirm that the second attempt is rejected.

Ways to go further

Affiliate links: CHEAPUNO may earn a commission if you buy through them, at no extra cost to you.

Other problems readers raise

Unified SaaS or AI roadmap? Fixing fragmented workflow chaos

How to log silent work to prevent bugs and credit effort

Is Apple Vision Framework better than Tesseract for OCR?

Can passkeys replace passwords for your app login?

Does your AI SaaS stack use Stripe as a merchant of record for tax compliance?