Retries & dead-letter

How Nevo retries failed endpoint deliveries and what happens when every attempt fails.

When an endpoint delivery fails, Nevo retries it on an exponential schedule tied to the endpoint’s policy. Deliveries that exhaust the policy land in the dead-letter queue (DLQ) so you can inspect, diagnose, and replay them from the dashboard.

Failure model

A delivery fails when any of these happens:

  • Your endpoint returns a non-2xx HTTP status (any 4xx or 5xx counts).
  • The request times out (10 seconds today).
  • The connection can’t be established at all (DNS, TLS, network error).

On failure, Nevo schedules the next attempt. The delivery row shows status=retrying until either a later attempt succeeds or the budget is exhausted.

Retry policy

Every endpoint carries two fields that control its retry behaviour:

FieldDefaultWhat it controls
retry_max_attempts5Total attempts (including the first).
retry_backoff_base_seconds60Base delay in seconds; doubles each retry.

With the defaults a failing delivery produces attempts at roughly: t=0s → t=60s → t=120s → t=240s → t=480s (five total). After attempt 5, the delivery transitions to status=failed and the event lands in the DLQ.

Edit these fields from Endpoints → your endpoint → Retry policy in the dashboard. Changes apply to new deliveries only — in-flight retries use the policy that was in effect when they were scheduled.

Picking a policy

  • A low-volume endpoint on a flaky third-party service wants a longer base and more attempts — max=7, base=120s lets the delivery ride out a 20-minute incident.
  • A high-volume internal endpoint usually wants the defaults or lower — the system it’s calling will be healthy again within a few minutes or you have bigger problems.
  • Setting max=1 disables retry entirely for that endpoint. The delivery goes straight to DLQ on first failure.

Delivery attempts in the event detail

Open any event in the dashboard and the Deliveries section lists every attempt per endpoint:

  • A single successful delivery reads 200 · 142ms · 1x.
  • A delivery that retried twice before succeeding reads 200 · 93ms · 3x.
  • A delivery still retrying shows the attempt count and a countdown: retrying · 2x · next retry in 1m 46s.
  • A terminal failure reads failed · 5x and surfaces the last error message.

The event’s overall status reflects the aggregate of its deliveries:

  • delivered — at least one delivery succeeded (after any number of retries).
  • failed — every delivery exhausted its policy and terminally failed.
  • pending — one or more deliveries are still mid-retry.

A retry that succeeds after the initial round automatically walks the event back from failed to delivered.

Dead-letter queue

The DLQ view (Projects → your project → DLQ) lists every delivery that terminally failed across the project — one row per (event × endpoint). For each row you see:

  • The originating event (source, summary, timestamp), clickable to open the full event detail.
  • The endpoint URL that failed.
  • The last HTTP status code and error message.
  • How many attempts were made before giving up.

From here you can replay the event with one click, or open the event and use edit-and-replay to tweak the body before re-dispatching.

Signatures on retried requests

Every attempt — first try or fifth — carries the same HMAC signature scheme as live deliveries. The Nevo-Origin header is live for all attempts, even retries, since the retry is part of the same delivery lifecycle. Only explicit dashboard replays mark Nevo-Origin: replay.

Plan availability

Retries ship on every plan. DLQ retention follows your plan’s replay retention window:

TierDLQ retention
Hobby7 days
Hacker14 days
Pro30 days
Scale90 days

After the retention window, DLQ rows age out alongside their parent events.