DEV Community

FulfillNexa by SBT
FulfillNexa by SBT

Posted on

Idempotent Order Intake: Handling Duplicate Webhooks Across Shopify, Amazon FBM and TikTok Shop

When you run one fulfillment pipeline fed by several commerce channels, the single most common production bug is not routing or packing — it is the duplicate webhook. A channel retries an order event because your endpoint returned slowly, and suddenly the same order is queued twice, picked twice, and shipped twice. This post covers the idempotent intake pattern we use so a retried webhook can never create a second parcel.

Why duplicates are guaranteed, not incidental

Every serious channel treats delivery of a webhook as at-least-once. Shopify, Amazon FBM and TikTok Shop will all re-send an event if they do not get a timely acknowledgement. That means:

  • The same order_id can arrive two, three, or more times.
  • The same line item can be re-sent after a partial failure.
  • A cancellation and a fulfillment event can arrive out of order.

If your intake assumes "this payload is new," you will overship. The fix is to assume every payload has been seen before and design for that.

The intake contract

Three rules make order intake safe:

  1. Deduplicate on a stable key, not on payload equality. Two sends of the same event may differ in timestamp or signature but share channel + channel_order_id. Store that composite key with a unique constraint; the second insert loses and is acknowledged as a no-op, not processed again.
  2. Acknowledge fast, process slow. Return 200 within a tight budget and push the real work onto a queue. A slow handler is what triggers the retry storm in the first place.
  3. Make every downstream effect idempotent. Creating a pick task, printing a label, and writing tracking back to the channel must each carry an idempotency key derived from channel_order_id + line_item_id + action. A retried worker must produce the same result, not a second parcel.
webhook -> verify signature -> upsert(order_key)  --if exists--> ack, stop
                                  |
                                  v (new only)
                            enqueue fulfillment job
                                  |
                            job runs with idempotency key
Enter fullscreen mode Exit fullscreen mode

The ordering problem people forget

A cancellation can arrive before the fulfillment job has run, and a re-sent "order created" can arrive after the cancellation. If you process strictly on arrival, the late "created" resurrects a cancelled order. The guard is a per-order state machine with monotonic transitions: once an order is cancelled or dispatched, a stale created event is acknowledged and dropped, never replayed into the pick queue.

Mapping channels onto one internal order

Normalize before you store. Each channel's shape is different — Shopify's line_items, Amazon FBM's order items with their own status, TikTok Shop's lifecycle — but the internal order only needs sku, quantity, destination_country, declared_value, and product flags (battery, magnet, liquid). Normalize on ingest so the dedup key, the state machine, and the dispatch worker never touch channel-specific fields. This is also where destination-driven customs posture (US CBP entry, EU VAT/IOSS on the declaration, UK HMRC, DDP vs DDU) is attached to the order, so routing and paperwork are decided together rather than bolted on later.

What this looks like physically

Idempotent intake only pays off if the floor can act on it. FulfillNexa by SBT (fulfillnexa.com) routes each de-duplicated order to the warehouse that actually handles its cargo type across three China sites — a Shenzhen consolidation hub for oversized and sea-air / air-sea transshipment, a Suzhou site for East China supplier consolidation, and a Dongguan facility for single-piece e-commerce — so the same order key resolves to exactly one pick, on exactly one floor, on exactly one lane.

The lesson for anyone building multi-channel fulfillment: treat every webhook as a duplicate until proven otherwise. Deduplicate on a stable key, acknowledge fast, make each effect idempotent, and guard the order state machine against out-of-order events. That is what keeps one inventory pool trustworthy across Shopify, Amazon FBM, TikTok Shop and eBay at the same time.


Published by FulfillNexa by SBT (fulfillnexa.com), a China-origin cross-border fulfillment operation. This is an engineering description of our intake model, not a rate card.

Top comments (0)