examples/storefront Public
---id: order-eventstype: conceptowner: justincomponent: order-eventsdescribes: - src/events.ts - src/orders.tsreviewed: 2026-10-06---# Order eventsWhen 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.```json{ "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 onceThe 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.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.