
Most online operators rely on webhooks to automate post-purchase workflows: add a buyer to your newsletter, grant course access, send a receipt, or trigger fulfillment. Payment and subscription platforms—Stripe, Gumroad, Lemon Squeezy, Paddle—all offer them, but they don’t behave the same way.
Webhooks are HTTP POST requests the platform sends to your server when an event occurs: a charge succeeds, a subscription renews, a refund is issued. Your endpoint receives a JSON payload, verifies it, and takes action. Simple in theory. In practice, timing windows, retry policies, and failure modes create gaps that can break your automation—and leave customers waiting.
When webhooks actually fire
Most platforms send a webhook immediately after an event completes on their side. Stripe fires charge.succeeded within seconds of card capture (Stripe webhooks documentation, checked November 2026). Gumroad queues its sale notification shortly after payment clears. Lemon Squeezy and Paddle follow similar patterns.
But “immediately” isn’t instant. Network latency, platform load, and internal queueing can introduce delays. Stripe’s documentation notes that webhooks may arrive out of order if multiple events fire in quick succession—so a customer.subscription.updated event can reach your server before the customer.subscription.created that preceded it.
For high-volume operators, this creates a design constraint: your webhook handler must be idempotent (safe to run more than once on the same event) and tolerant of out-of-order delivery. Store event IDs and check for duplicates before processing.
Retry logic and failure windows
When your endpoint is unreachable—server restart, DNS hiccup, deploy in progress—the platform retries. Retry schedules differ.
Stripe retries failed webhooks for up to three days, with exponential backoff: the first retry happens after a few seconds, subsequent attempts spread over hours (Stripe retry best practices, checked November 2026). If all retries fail, the event is marked as failed in your dashboard. You can manually resend it, but there’s no automatic recovery after the window closes.
Gumroad retries for 72 hours. Lemon Squeezy follows a similar three-day window. Paddle’s retry schedule is shorter—24 hours—and its documentation warns that events older than that cannot be replayed (Paddle webhooks overview, checked November 2026).
This matters if you’re migrating servers, changing endpoints, or experiencing downtime. A 48-hour outage on Paddle means lost events. On Stripe, you have a narrow recovery window—but only if you notice the failure and resend manually.
Where webhooks break silently
The most common failure mode isn’t a hard error—it’s a silent drop. Your server returns HTTP 200 (success) too early, before the database write completes. The platform marks the webhook as delivered. Your workflow never runs.
Always acknowledge the webhook after you’ve committed the critical action—writing the order to your database, adding the email to your list, or queueing the follow-up job. Return 200 only when the work is durable. If your server crashes mid-process, return a 5xx status so the platform retries.
Another silent failure: signature verification bugs. Every platform signs its webhook payloads so you can confirm they’re authentic. Stripe uses HMAC-SHA256 with a signing secret; Gumroad appends a hash parameter. If your verification logic is wrong—comparing the raw body instead of the canonical form, or using the wrong secret after a key rotation—you’ll reject legitimate webhooks and never know why.
Test your handler with the platform’s CLI tool (Stripe offers stripe listen) and confirm that replayed events trigger the same outcomes as live ones.
Designing around webhook unreliability
Webhooks are notifications, not the source of truth. Treat them as a prompt to check the platform’s API, not as the definitive record of what happened. When a charge.succeeded arrives, query the Stripe API for the charge object and verify its status before granting access.
For mission-critical workflows—access provisioning, high-value purchases—add a fallback: poll the platform’s API periodically for recent transactions and reconcile against your database. If a webhook was dropped or delayed beyond the retry window, your polling job catches it within minutes or hours instead of leaving the customer stuck.
Store the raw webhook payload in a separate table before processing it. If your automation logic changes or you discover a bug weeks later, you can replay old events from your archive without asking the platform for help.
Webhooks are the fastest path from payment to fulfillment, but they’re not guaranteed delivery. Build your automation to survive the gaps, and you’ll spend less time manually fixing stuck orders.
One Two Three Send covers tools, workflows, and infrastructure for online operators. Subscribe to get one focused article every morning.
