The fastest way to lose a day of delivery time is a CSV order export. The fix is webhooks: when an order is created in Shopify, it should reach the pick queue in seconds.
Shopify sends an orders/create webhook. Your job is to make it idempotent and fast.
app.post('/webhooks/shopify/orders-create', async (req, res) => {
const orderId = req.body.id;
// 1. Acknowledge fast (Shopify retries on timeout)
res.sendStatus(200);
// 2. Idempotency guard: Shopify WILL deliver duplicates
if (await orderQueue.exists(orderId)) return;
// 3. Normalize into the warehouse order shape
await orderQueue.enqueue({
externalId: orderId,
source: 'shopify',
lines: req.body.line_items.map(li => ({ sku: li.sku, qty: li.quantity })),
shippingAddress: req.body.shipping_address,
});
});
Three lessons from production:
- Return 200 immediately, do the work async. A slow handler turns Shopify's retries into duplicate orders.
-
Idempotency is not optional. You will get the same
order_idmore than once. Key the queue on the external ID. - Map SKUs, never product titles. Titles change and are not unique. The SKU is the only stable join between Shopify and the warehouse.
The point is to remove the human from the order path. Once orders flow through webhooks, "when did my order reach the warehouse" stops being a question.
Top comments (0)