Checkout flow: call charge endpoint, get back status: approved synchronously, show the confirmation page, write the order to the DB as paid. Standard stuff.
Then the webhook for the same transaction lands 2-6 seconds later. Most of the time it just confirms what we already knew. Except for a window where the issuer sends a late decline after the gateway already told us approved — card network risk check flagged it post-authorization, something like 1 in 3000 transactions on one acquirer.
Our order write happened on the sync response. The webhook handler had no idea an order even existed yet when it tried to update status, because the DB write from the sync path hadn't committed. Webhook processed against a row that didn't exist, silently no-op'd, and we shipped a product against a transaction that got reversed six hours later in the settlement file.
Fix was boring: webhook handler now upserts instead of updates, and order state transitions go through a queue instead of direct writes so ordering is enforced regardless of which path (sync response or webhook) arrives first.
Curious how other people handle the case where your own synchronous API response can't be trusted as final. Do you delay fulfillment until the webhook confirms, even on providers where that adds real latency to checkout?
Top comments (0)