id | payload | delivered_at |
---|---|---|
01HRD0B6MTEWZZ86ZVVM | {"event_type": "order.created"} | 2023-10-14T22:11:20+0000 |
delivered_at
column to determine if you’ve handed over the event to the webhooks gateway / message broker, so you can delete it afterwards. Use the id
field as the Idempotency key
so you can uniquely present each webhook to the gateway.
invoice
resource, instead of sending invoice.update
every time the state of our invoice
changes, we should generate a new event — invoice.{state}
for each state change. In the former method, ordering would be required to determine what order the updates happened, whereas the latter does not require ordering because final state does not change. A paid invoice cannot be unpaid.
shipment
. Instead of sending shipment.update
for every time the package arrives at a new facility, we should generate a new event— shipment.milestone
for each milestone achieved include a timestamp. With this, we can correctly present the shipment history regardless of the order in which the events arrive.
customer
and invoice
object, and an invoice
belongs to a customer
. The system should fail If we try to process an invoice.created
webhook when we’re yet to process the necessary customer.created
. This is fine because webhooks are an eventually consistent system and most providers will (should) implement a retry. With this in mind, it is ok to reject the webhook with the expectation that eventually the customer.created
webhook will arrive and the invoice.created
webhook will be retried and it will balance out.