A webhook handler can return a successful response twice and still create two warehouse pick tasks. An integration test should check the business side effect after a repeated delivery.
This is a small runnable teaching example from YX Fulfillment, not a description of the company's production system.
Delivery identity and business identity answer different questions
Shopify's delivery verification guide explains that webhook deliveries can repeat. It distinguishes the webhook delivery identifier from the event identifier shared by deliveries associated with the same merchant action.
For HTTPS delivery, authenticate the request before trusting its identifiers or payload. Keep request verification separate from the example below, which starts with an already authenticated, normalized message.
A delivery key answers whether this delivery has been handled. A business key answers whether the intended operation already exists. For a warehouse release, that second key may combine the store, order and an explicitly approved release revision. The right revision rules depend on whether the business supports split releases, amendments and cancellations.
Do not invent a new release revision merely because a delivery is retried.
A small test that can catch duplicate work
Save this as release-demo.cjs and run node release-demo.cjs.
const assert = require('node:assert/strict');
const deliveries = new Set();
const pickTasks = new Map();
function acceptRelease(message) {
const { shop, deliveryId, orderId, releaseRevision, sku, quantity } = message;
assert.ok(shop && deliveryId && orderId && releaseRevision && sku);
assert.ok(Number.isSafeInteger(quantity) && quantity > 0);
const deliveryKey = JSON.stringify([shop, deliveryId]);
const businessKey = JSON.stringify([shop, orderId, releaseRevision]);
const proposed = { sku, quantity };
if (pickTasks.has(businessKey)) {
// Same operation with different contents needs a decision, not another pick.
assert.deepEqual(pickTasks.get(businessKey), proposed);
deliveries.add(deliveryKey);
return 'existing';
}
if (deliveries.has(deliveryKey)) throw new Error('Delivery state is inconsistent');
pickTasks.set(businessKey, proposed);
deliveries.add(deliveryKey);
return 'created';
}
const request = {
shop: 'example-store', deliveryId: 'delivery-a', orderId: 'order-17',
releaseRevision: 'approved-1', sku: 'POUCH-BLUE', quantity: 2
};
assert.equal(acceptRelease(request), 'created');
assert.equal(acceptRelease(request), 'existing');
assert.equal(acceptRelease({ ...request, deliveryId: 'delivery-b' }), 'existing');
assert.equal(pickTasks.size, 1);
assert.throws(() => acceptRelease({ ...request, quantity: 3 }));
assert.equal(pickTasks.size, 1);
console.log('Repeated deliveries created one unchanged pick task.');
The changed-payload test matters. Silently accepting a different quantity under the same release key can conceal an order amendment. The example rejects that conflict so the workflow has to resolve it deliberately.
What this demonstration leaves out
The in-memory collections are deliberately limited. They do not survive a restart, coordinate multiple workers, validate SKU mappings or call a warehouse service. A successful run does not prove a production integration is ready.
In a durable design, enforce uniqueness in persistent storage and make the delivery record and intended business operation consistent across failures. If processing is asynchronous, commit the incoming message or outbox work before acknowledging durable acceptance. A process crash between recording a delivery and recording its work needs an explicit recovery path.
An external warehouse API adds another boundary. Use its idempotency mechanism if available. If a release request times out after it may have been accepted, look up the existing release before sending another one. A local database transaction cannot roll back a parcel already released by an external system.
Add the cases a warehouse operator will encounter
Exercise a duplicate delivery, two workers racing on one release, a restart after persistence, an unknown SKU, a cancellation after acceptance and a changed quantity under an existing release key. Check both the integration record and the resulting warehouse instruction.
For a store connecting to a fulfillment provider, the useful acceptance question is concrete: after the same approved release reaches the integration twice, how many pick tasks exist, and how can an operator prove which one belongs to the order?
Testing repeated order events before warehouse release. Illustrative scene.

Top comments (2)
The two-keys split is the same split that decides what the test can claim. A 200 from the handler is a claim about the handler - "the message was accepted" - and a pick task is a claim about the world - "the operation happened". Testing the response verifies the first and quietly assumes the second, which is how suites go green while the warehouse double-picks. Delivery identity and business identity are the fix because they separate hearing about the operation from the operation itself: at-least-once delivery means the retry isn't an anomaly, it's the environment keeping its own contract, so idempotency stops being error handling and becomes the actual semantics. Dedupe on what the operation means, not on how many times you heard about it - and the test that matters is the one that reads the world afterward, not the one that read the response.
The changed-payload case is the one people skip. Same release key, different quantity, and the handler should not just accept it quietly.