At-least-once vs. exactly-once delivery, explained for API integrators
The real distributed-systems delivery guarantees, and how an idempotency key lets an at-least-once system like PostGate behave like exactly-once from your integration’s point of view.
At-least-once delivery retries a message until it is acknowledged, accepting possible duplicates; exactly-once promises no duplicates and no losses. True exactly-once across two independent systems over an unreliable network is famously hard — most systems claiming it actually do at-least-once delivery plus deduplication on the receiving end, which produces the same observable result.
Distributed systems have to choose how they handle a message when the acknowledgment for it goes missing — resend and risk a duplicate, or don't resend and risk losing it entirely. That choice has a name — a delivery guarantee — and understanding it explains why PostGate can retry aggressively behind the scenes without you ever seeing a post go out twice.
PostGate handles OAuth, publishing and delivery evidence for every network through one API. Start free or read the docs.
What are the three delivery guarantees?
- At-most-once. A message is sent once, with no retry — if it's lost, it's gone. Simple, but unsafe for anything you can't afford to drop.
- At-least-once. A message is retried until it's acknowledged, which means it can be delivered more than once — the sender would rather risk a duplicate than risk a loss.
- Exactly-once. A message is delivered exactly one time, no duplicates, no losses. True exactly-once delivery across two independent systems over an unreliable network is famously hard — most systems that claim it are really doing at-least-once delivery plus deduplication on the receiving end, which produces the same observable result without requiring a physically impossible guarantee.
Why does a publishing API default to at-least-once?
Between PostGate and a destination platform, and between your client and PostGate, the honest default is at-least-once: retry on ambiguous failure rather than silently drop the request, because dropping a scheduled launch post is worse than occasionally needing to retry one. Per Errors & retries, PostGate already retries provider delivery internally on transient failures — that's at-least-once behavior at the platform-delivery layer, working in your favor.
How does an idempotency key make at-least-once look like exactly-once?
At-least-once plus deduplication is exactly what an Idempotency-Key gives you at the API boundary: your client can retry the same POST /api/posts call as many times as it needs to — after a timeout, after a crash, after a redeploy — and PostGate treats every retry carrying the same key as the same logical request, returning the original post instead of creating a new one. See Idempotency & safe retries for the mechanism and the 72-hour window it holds a key for, and Preventing duplicate posts for the practical guide.
From your integration's point of view, the result behaves like exactly-once delivery — one logical publish, one post, no matter how many times the underlying call was retried. Underneath, it is still at-least-once with deduplication; the distinction matters for how you reason about it, not for the outcome you see.
The same pattern, mirrored on the way back out
Webhook delivery works the same way in reverse: PostGate retries a delivery to your endpoint when it times out or returns a non-2xx status, which means your consumer can receive the same event more than once. The fix is identical in shape — deduplicate on the event's stable id (sent as X-PostGate-Event-Id) — and it's covered in full in Webhook retry best practices.
The takeaway for your own integration
Don't try to build true exactly-once delivery yourself — treat every layer of a publishing pipeline as at-least-once by default, and add deduplication at each boundary: idempotency keys on the way in, event IDs on the way out. That combination is what a retry-safe publishing integration actually is.
Frequently asked questions
What is at-most-once delivery?
At-most-once means a message is sent once, with no retry — if it is lost, it is gone. It is the simplest guarantee, but unsafe for anything you cannot afford to drop, which is why publishing pipelines prefer at-least-once: retrying on ambiguous failure beats silently dropping a scheduled post.
How does an idempotency key make retries safe?
An Idempotency-Key gives you at-least-once delivery plus deduplication at the API boundary. Your client can retry the same POST /api/posts call as many times as needed — after a timeout, a crash, or a redeploy — and every retry carrying the same key is treated as the same logical request, returning the original post instead of creating a new one. PostGate holds a key for a 72-hour window.
Can I receive the same webhook event more than once?
Yes. Webhook delivery is at-least-once in reverse: PostGate retries a delivery to your endpoint when it times out or returns a non-2xx status, so your consumer can see the same event twice. The fix is to deduplicate on the event’s stable id, sent as the X-PostGate-Event-Id header.
Should I try to build true exactly-once delivery myself?
No. Treat every layer of a publishing pipeline as at-least-once by default and add deduplication at each boundary instead: idempotency keys on requests going in, stable event IDs on webhooks coming out. That combination behaves like exactly-once from your integration’s point of view without requiring a guarantee that is practically impossible across independent systems.
