What is a at-least-once delivery?
At-least-once delivery means the source guarantees every event will be delivered one or more times — never zero, but possibly several. It's the default contract for webhook providers because exactly-once delivery over a network is provably impossible without consensus protocols. Network partitions, source crashes between "delivered" and "ack received," and receiver timeouts after the work is done all create ambiguity, and the source's only safe response is to retry. Your handler's job is to make at-least-once behave like exactly-once, by being idempotent. Plan for duplicates from day one, plan for out-of-order duplicates, and keep dedup retention beyond the source's max retry window.
Webhook providers almost universally guarantee at-least-once delivery. The contract: every event will eventually arrive at your endpoint, but it may arrive multiple times. The opposite (at-most-once: every event arrives zero or one times) is rare and unsafe — it means lost events are possible, which is unacceptable for events like payments.
Why at-least-once and not exactly-once? Exactly-once delivery over a network is provably impossible without consensus protocols (and even then, it's expensive). Network partitions, source crashes between "delivered" and "ack received," receiver timeouts after the work is done — all of these create ambiguity. The source's only safe response to ambiguity is to retry. So duplicates are not a bug; they're the cost of guaranteed delivery.
The implication for your handler: you must make at-least-once *behave like* exactly-once, by being idempotent. Duplicates arrive; your handler dedupes on event ID; the business effect is the same as if the event had been delivered exactly once. This is where the idempotency requirement comes from — it's the receiver's job to compensate for the network's at-least-once nature.
Three practical consequences:
- Plan for duplicates from day one. Don't ship a handler with "we'll add idempotency later." Every untested code path under retry will eventually break in production. - Plan for out-of-order duplicates. Event A retry #2 may arrive before event A retry #1's ack times out. Your idempotency check must work regardless of arrival order. - Plan for far-apart duplicates. Stripe's retry window is 3 days. An event delivered at 12:00 may arrive again at 11:59 the next day. Your idempotency store needs retention beyond the source's max retry window.
A handful of providers offer optional exactly-once-ish guarantees via dashboard settings or API features (e.g., Kafka's transactional producers within a single broker scope). For inbound webhook integrations from external sources, ignore those — they're internal to the source's infrastructure and don't extend across the network boundary.
If you control both ends — emitting webhooks to your own customers — you also provide at-least-once. The customer's contract with you is "every event at least once;" the customer's contract with their handler is "implement idempotency." Encourage idempotency in your developer docs; provide an event ID prominently in the payload; make duplicate detection at the receiver as easy as possible.
See At-Least-Once Delivery in real traffic
WebhookWhisper captures every webhook with full headers, body, signature, and timing — so concepts like at-least-once delivery stop being abstract and become something you can inspect.
Start Free