Core · The same event twice should do the work once.
Idempotency
Webhooks are delivered at least once, not exactly once. Shopify, Stripe, Razorpay and your own retries can all hand you the same event again, and your workflow can't tell unless you make it.
Try this
Run each experiment in the simulator above, then tick it off.
Key ideas
Pick a natural key
Every event carries something unique: an order ID, a payment ID, a submission ID. That's your idempotency key. Never a timestamp or a customer name.
Check before you create
Before a step creates anything, look the key up. Found it? Skip or update. Not found? Create it and record the key.
Prefer upserts
“Create or update by email/ID” actions are idempotent by design. A plain “Create” is not.
In your Pabbly workflows
Put a lookup step before your “Create contact” or “Create invoice” action: search the sheet or CRM by the order ID, then add a Filter so the create path only runs when nothing was found. Or use the app's “Create or Update” action keyed on the order ID or email. That one filter is what stops a payment gateway's retry from issuing a second invoice.
Check yourself
0/2Get every question right to mark this lab done. Wrong answers let you try again.
Q1. Stripe delivers the same payment_intent.succeeded event twice. What's the best idempotency key?
The payment ID is identical on every retry and unique per payment. Arrival time and a fresh random ID differ on each delivery, and an email repeats across different, legitimate payments.
Q2. Which action is naturally idempotent?
Setting a field to a fixed value ends in the same state no matter how many times it runs. Creating, sending and appending all stack up.
Lab complete
Marked done on this device. On to the next one.
Watch next
Searches for “idempotency” on the channels worth your time.