Stripe Webhook Replay or Duplicate Events Are Double-Applying Changes
Quick Answer
Stripe can retry webhook delivery, and duplicate event handling becomes dangerous if your endpoint is not idempotent. If each webhook blindly writes state again, retries look like extra purchases or extra upgrades. Start with "Store processed event IDs" before making broader code changes.
Quick Fix Summary
| Most likely cause | Stripe can retry webhook delivery, and duplicate event handling becomes dangerous if your endpoint is not idempotent. If each webhook blindly writes state again, retries look like extra purchases or extra upgrades. |
| Fastest fix | Store processed event IDs |
| Use this page if | Credits are added twice after one payment |
You're in the right place if...
- !Credits are added twice after one payment
- !A subscription update runs more than once
- !Webhook retries create duplicate rows or duplicate entitlements
Why this happens
Stripe can retry webhook delivery, and duplicate event handling becomes dangerous if your endpoint is not idempotent. If each webhook blindly writes state again, retries look like extra purchases or extra upgrades.
Fix
Store processed event IDs
Make the webhook idempotent by recording each Stripe event ID and ignoring repeats once the first valid processing succeeds.
Guard writes with unique constraints
For credits, orders, or entitlements, use a unique key that makes duplicate inserts fail safely instead of duplicating state.
create table if not exists stripe_events ( event_id text primary key, event_type text not null, processed_at timestamptz not null default now() );
Separate verification from mutation
Verify the signature first, then check whether the event was already processed, and only then apply state changes.
Patch the generated webhook handler
Tell Lovable to make the Stripe webhook idempotent instead of assuming each event arrives once.
Copy this prompt
Audit the Stripe webhook handler in this app for replay and duplicate-event safety. Verify the signature, persist the Stripe event ID, and skip any mutation if that event was already processed once successfully.
Prevent this next time
Every payment webhook should be written as if Stripe may send it twice, because in real systems it often will.
Frequently Asked Questions
Retries happen when the endpoint times out, errors, or Stripe does not get a clear success response quickly enough.
No. Signature verification proves the event came from Stripe, not that you have not already processed it.
Related fixes
Weekly Signals
Get the next fix, switch, or warning before it hits your build.
Join builders getting the community signals, fix patterns, and tool shifts that matter before they show up everywhere else.
Follow the signals →