OneShot

All packsSaaS Billing + Tax CoreSolve

stripe webhook out of order events race condition

Stripe doesn't guarantee webhook delivery order

Stripe explicitly does not guarantee event ordering; applying subscription webhooks in arrival order instead of event.created order corrupts cached state (D5).

3 of 3 runs passedOne decision inside SaaS Billing + Tax Core (nextjs-prisma-postgres).

What goes wrong

Stripe states plainly that it does not guarantee webhook delivery order. Code that applies each subscription.updated payload to the local cache in the order it happens to arrive can let a stale event (a past_due from three retries ago) overwrite a newer one (the customer already paid and is active) -- the account's displayed state becomes wrong until the next event happens to fix it, or never.

Why agents get it wrong

In normal operation and in almost every manual test, webhooks do arrive in order, so ordering bugs don't show up until Stripe actually retries something or two events fire close together in production -- an agent has no local signal that ordering matters unless the architecture document says so up front.

What SaaS Billing + Tax Core pre-decides

D5 applies an incoming subscription object to the cache only if event.created is greater than or equal to the row's stored lastEventCreated timestamp -- otherwise the event is a no-op, returned as {stale: true}. A different subscription id (churn-and-return, D2) only replaces the row if the existing one is no longer live; if it is, the replacement is refused and logged as an orphan rather than silently overwriting a live subscription.

Source: ARCHITECTURE.md D5

Coming soon — $149Full receipt and details for SaaS Billing + Tax Core

Related problems