All Glossary Terms
Reliability

What is a event ordering?

Event ordering is the property of whether webhooks arrive at the receiver in the same order the events occurred at the source — usually they do not. Stripe, GitHub, and Shopify all explicitly disclaim ordering guarantees. Retries break ordering: if event A times out and is retried while event B succeeds on first try, B arrives before A. Design handlers to be order-independent: don't trust event sequence to drive business decisions, use the source-issued timestamp inside the payload (not arrival time), and re-fetch the source object's current state when ordering matters instead of trusting payloads to reflect latest state.

Webhook providers do not generally guarantee event ordering. Stripe's docs say it directly: "We do not guarantee delivery of events in the order they are generated." GitHub doesn't guarantee order. Shopify doesn't. Most providers explicitly disclaim ordering, and the ones that don't disclaim usually don't actually preserve it under retry.

Why ordering breaks: retries. If event A times out and is retried while event B succeeds on first try, B's "delivered" timestamp is earlier than A's even though A happened first. Multiply this by parallel delivery workers on the source side, network jitter, and partial outages, and ordering is unrecoverable from the wire alone.

What this means for your handler:

- Don't rely on arrival order to make business decisions. "I got subscription.created then subscription.canceled, so the user signed up and then cancelled" is a logical claim that may be false in practice — they may have arrived in reverse order, and the user is actually still subscribed. - Re-fetch the source object's current state when ordering matters. Instead of trusting the event payload to reflect the latest state, the handler treats the event as "something changed; go ask the API for the truth." Slower, but correct. - Use timestamps from the event payload, not arrival time. Most events include a created_at or similar — that's the authoritative ordering signal, not when your server received the request. - Be careful with "current state" fields in payloads. If event A is "subscription updated to active" and event B is "subscription updated to canceled," and they arrive B-then-A, naïvely applying each in order leaves the local state as "active" — wrong. Always reconcile against the source.

The exception: a handful of providers do guarantee per-resource ordering, where events about the same object arrive in source-order but events about different objects can interleave. Stripe behaves this way for the same customer or payment_intent — events about pi_abc arrive in order. This is undocumented but observable; don't rely on it.

For internal event-driven systems (Kafka, Pulsar) you can get stronger ordering by partitioning on a key — all events for the same user go to the same partition, and within a partition order is preserved. Webhooks don't expose this knob; if you need ordering, you build it yourself: pull events into a queue keyed by source-object-ID and process per-key in order.

Architectural rule: design handlers to be order-independent whenever possible. The handlers that survive at scale assume "events arrive whenever they arrive, in whatever order; reconcile against the source." Handlers that assume order eventually break under retry.

See Event Ordering in real traffic

WebhookWhisper captures every webhook with full headers, body, signature, and timing — so concepts like event ordering stop being abstract and become something you can inspect.

Start Free