5 lessons

Webhooks

Your contract running against someone else’s server: delivery states, retries, duplicate events, ordering you must not assume, and the signature that makes any of it trustworthy.

RequirementConsumersResource ModelStyleContractValidationAuthorizationErrorsIdempotencyPaginationVersioningObservabilityEvolutionTrade-offs

Every lesson below names the consumers, the design question and the guarantee before recommending anything. Recommendations come with what they cost, when not to use them, and how they evolve.

Webhooks: The Inverted Contract

A webhook flips the roles: the provider becomes the client, calling an endpoint the consumer operates. Delivery is asynchronous and at-least-once, so the event envelope — event id, delivery id, type, timestamp — is what makes the stream usable, not the payload.

Q · When the provider calls the consumer instead of the other way around, what must the event contract state for the consumer to build something reliable on it?
Webhook Delivery: States, Retries, Redrive
▶ lab

Every event delivery is a little state machine: queued → attempting → delivered, or failed → retrying → dead. The retry schedule, the definition of "delivered", and the dead-letter escape hatch are contract clauses both sides build against.

Q · What exactly does the provider promise about when, how often, and for how long it will try to deliver each event — and what happens when it gives up?
Consumer-Side Idempotency

The provider promised at-least-once, so duplicates are not a bug — they are scheduled. Exactly-once processing is an illusion the consumer manufactures locally: record the event_id, process each id exactly once, and make the recording atomic with the effects.

Q · When the same event arrives twice — and it will — how does the consumer make the second arrival a no-op instead of a second shipment?
Webhook Ordering: Assume None

Retries, parallel dispatch and redrives mean events arrive in whatever order the network permits — `order.shipped` before `order.paid` is routine. Consumers that apply event payloads as state, in arrival order, corrupt their data; the contract must say so and give them a defense.

Q · What may a consumer assume about the order in which events arrive — and since the honest answer is "nothing", how do they keep their state correct anyway?
The Webhook Security Contract

A webhook receiver is an unauthenticated public POST endpoint that triggers business logic — unless the contract says how events are signed, how timestamps bound replay, and how secrets rotate. Signature verification is the consumer's only proof that an event is yours.

Q · How does a consumer prove an incoming event actually came from the provider, is unmodified, and is not a replay — and how does the contract make that verifiable forever, across secret rotations?