Your target was down for an hour. Nothing was lost.

September 15, 2026

A target went down at 14:00 and came back at 15:00. Somebody deployed a bad migration, or the vendor had a bad afternoon. The question that matters is what happened to the requests your callers made during that hour.

On a queued target, the answer is that they were delivered late and nobody had to do anything.

What queued delivery actually promises

A queued target accepts the caller's request straight away, with a 202 and a request id, and delivers it in the background. Your caller is finished at that point. Whether the target answers in 40 milliseconds or after an hour of refusing connections is not something your caller waits to find out.

Delivery is at-least-once. A target that is slow to answer but did receive the request can see it twice, so the receiving end should be able to recognise a repeat. That is the trade, and it is the right way round: a duplicate you can detect beats a delivery you silently lost.

The retry schedule, in full

A failed delivery is retried up to 14 times in total by default, with the wait doubling after each attempt, a ceiling on any single wait, and a little randomness added so that a target coming back up does not get every stalled delivery in the same instant.

Retries happen on 429, 500, 502, 503 and 504, and on a connection that never completed. A 400 or a 422 is not retried, because sending the same malformed request again would produce the same answer.

If the target sends a Retry-After, its wait wins over ours. A vendor telling you when to come back knows something we are only guessing at.

All three are per-target settings: attempts from 1 to 14, the backoff multiplier from 1.0 to 5.0, and the list of status codes worth retrying. A target you know recovers in seconds and one that recovers in hours should not share a policy.

An hour of downtime fits inside the default schedule with room left over.

Watching one request move

Take the request id from the 202 and ask for its receipts. You get one entry per target the request fanned out to, each with its status, which attempt it is on, when it was enqueued and last updated, and the terminal error if it ended badly. A delivery still moving answers from the live tracking copy and a finished one from durable storage, in the same shape, so polling the same id until the status stops changing works.

Or do not poll. Give a target a completion callback URL and we tell you when its delivery reaches a terminal state.

When the retries run out

A delivery that fails every attempt lands in the dead-letter queue with the original body and headers intact. You can read it, replay it once the target is healthy, or discard it, from the panel, the REST API or an agent over MCP.

Entries are kept for up to 30 days from the failure, or until you clear them, and they are never written to a database. A replay is a real send: it costs what the original send cost, because it is doing the same work again.

Two things worth knowing before you rely on it. The queue has a capacity cap, and if you dead-letter faster than you triage, the oldest entries are discarded to make room. The count of what was discarded is reported alongside the entries, so this is visible rather than silent, but a dead-letter queue is a triage tool and not an archive. And one inbound request that fans out to three targets can produce three separate entries, since each target failed on its own terms.

The modes that are not retried

None of this applies to a synchronous or a streaming target. Both answer inside your caller's own HTTP response, on a connection that is still open and waiting. There is no background left to retry into: by the time the delivery failed, your caller already has the failure. Retrying is your decision to make, with the response in your hand.

Choosing queued for a target is choosing to have this problem handled. Choosing synchronous is choosing to handle it yourself, usually because your caller genuinely cannot proceed without the answer.

What you do not have to build

An outbox table. A scheduler that walks it. Backoff arithmetic that somebody gets wrong once. A second table for the ones that will never succeed, and an internal page for looking at that table, which gets written the week after the first incident and is never improved again.

That machinery is not hard. It is just never the thing you set out to build, it has to be right at exactly the moment everything else is wrong, and every service that talks to a flaky target needs its own copy.

Connect everything. Deploy nothing.

No credit card required.