examples/storefront Public
id: order-events
type: concept
owner: justin
component: order-events
describes:
- src/events.ts
- src/orders.ts
reviewed: 2026-10-07
Order events
When an order changes state, storefront-api puts a message on the order-events queue so other parts of the shop can react without being called from the payment path.
{ "type": "order.paid", "order_id": "5d0c...", "at": "2026-10-06T17:02:11.000Z" }
| Type | Sent by | When |
|---|---|---|
order.paid |
markPaid |
the order is paid after the call |
order.cancelled |
cancelOrder |
the call cancelled the order |
Both are sent from src/orders.ts, after the D1 write, inside the OrdersService call the webhook makes ([[payment-webhook]]).
At least once
The D1 write and the queue send are two steps, and either can fail on its own. The order is the source of truth, so the write goes first. markPaid then sends order.paid whenever the order ends up paid, including when an earlier delivery already marked it. If the send fails, the call throws, the webhook answers 500, Stripe retries, and the retry sends the event.
The price is duplicates: a consumer can see order.paid for the same order more than once, and must act on it once. The order id is the dedupe key.
The consumer today is [[fulfilment]]. Messages are small and carry no order details. A consumer that needs the address or the lines asks OrdersService for them when it handles the message, so it always works from the current order.