examples/storefront Public
id: fulfilment
type: concept
owner: justin
component: fulfilment
describes:
- workers/fulfilment/src/**
- migrations/0004_shipments.sql
reviewed: 2026-10-07
Fulfilment
The storefront-fulfilment Worker turns paid orders into shipments. It consumes the order-events queue ([[order-events]]) and talks to two things: storefront-api's OrdersService over the ORDERS service binding, and the warehouse's HTTP API at WAREHOUSE_URL.
Handling an event
For each order.paid message:
OrdersService.forFulfilment(order)returns the current order. If it is notpaidany more (already fulfilled, which means this message is a repeat, or cancelled), the message is acked and nothing else happens.POST {WAREHOUSE_URL}/v1/shipmentswith the address and the lines, andIdempotency-Key: order-<id>.OrdersService.recordShipment(order, shipment_id)moves the order tofulfilledand stores the shipment id.
Every other event type is acked and ignored. The steps are drawn in the order fulfilment flow on the Architecture tab.
Failures
Each message in a batch is acked or retried on its own, so one bad order does not hold back the rest. Any error (the warehouse answering 4xx or 5xx, a timeout, OrdersService failing) retries the message after backoff(attempts): 30 seconds, doubling, at most an hour. After six retries the queue moves the message to order-events-dlq. Messages there are orders a person has to look at; the logged error says why each one failed.
Why repeating step 2 is safe is in [[0007-at-least-once-with-idempotency-keys]].
Running it locally
npx wrangler dev -c workers/fulfilment/wrangler.jsonc with WAREHOUSE_URL and WAREHOUSE_TOKEN in .dev.vars next to that config. With storefront-api running in another terminal, wrangler connects the service binding and the local queue.