A retry should repeat an attempt, not repeat the business outcome. If a timeout causes your integration to create the same supplier order twice, the missing control is usually idempotency: every create-order operation needs a stable key that lets the supplier recognize that a retry belongs to an order already created.
Why duplicate orders happen even when the integration “works”
Imagine the supplier saves an order successfully but its API response is delayed. Your middleware times out and retries. If the second request looks new, the supplier creates another order. Both requests were technically valid; the business result was wrong.
This is common around network errors, worker restarts, queue redelivery and webhook retries because reliable systems intentionally retry uncertain operations. The protection must therefore live at the business-action level.
Use an idempotency key that survives retries
Create a deterministic reference from the store order, supplier and operation type. Every retry for the same supplier order uses the same key. The supplier or middleware stores the first successful result and returns it again when that key reappears.
Do not generate a new random request ID on every retry and call that idempotency. A unique transport ID proves requests are different; an idempotency key proves they belong to the same business action.
Treat unknown outcomes as a separate state
After a timeout, the correct state is often not “failed.” It is “unknown.” The order may exist at the supplier even though the response never reached you. Before sending create-order again, query the supplier by your external reference.
A robust state model might be prepared, submitted, outcome unknown, confirmed with supplier order ID, rejected and cancelled. That makes it possible to handle uncertainty without creating inventory and cash-flow surprises.
Reconciliation catches what events miss
Run a scheduled comparison between store orders and supplier orders. One storefront order should map to the expected number of supplier orders. Extra supplier IDs for the same warehouse and items should create an alert.
Reconciliation is valuable because webhook processing can be perfect for weeks and still fail during one short network incident. A daily control gives you a second route to discover the problem before both parcels reach the customer.
What to do when both parcels are already moving
- Identify which supplier orders and tracking numbers are duplicates.
- Try to cancel or intercept the extra shipment.
- Contact the customer before the second parcel creates confusion.
- Provide a simple return process if interception is impossible.
- Reconcile supplier charges and refunds.
- Add a regression test that simulates a timeout after order creation.
The expensive part of a duplicate is not only the extra product. It can create another shipping charge, another return, more support time and an unnecessary refund risk.
Duplicate fulfillment can become a cash-flow problem at scale
A store processing hundreds of orders can duplicate an entire retry batch if a worker configuration is wrong. That can consume supplier credit or card limits before the merchant notices.
This is especially dangerous when the business already depends on delayed processor payouts. The cash-flow mechanics discussed in Shopify Payments payout holds after scaling become much worse if supplier charges are duplicated by an integration fault.
Frequently asked questions
Are webhooks guaranteed to arrive once?
No. Systems may deliver the same event more than once, so consumers should be designed for duplicate delivery.
Where should idempotency be implemented?
Ideally at the endpoint that creates the irreversible business outcome. Middleware can add protection, but the final supplier-order creation also benefits from stable external references.
Is increasing the API timeout enough?
No. It may reduce some retries but does not make duplicate creation impossible. The business action still needs duplicate protection.

