Webhook retries

If your endpoint fails to respond with a 2xx status within 10 seconds, Aeses retries the delivery. The retry schedule and rules are deterministic so you can build around them.

Retry schedule

A failed delivery is retried up to 7 times with the following backoffs from the original attempt:

| Attempt | Delay from previous | Total elapsed | | ------- | ------------------- | ------------- | | 1 | — | 0 | | 2 | 30 seconds | 30 seconds | | 3 | 2 minutes | ~2.5 minutes | | 4 | 10 minutes | ~12 minutes | | 5 | 1 hour | ~1 hour | | 6 | 6 hours | ~7 hours | | 7 | 24 hours | ~31 hours | | 8 | 72 hours | ~4 days |

After the 8th attempt fails, the delivery is marked exhausted and no further automatic retries occur. The event remains available via the webhook-deliveries API and can be replayed manually.

What counts as a failure

| Response | Retried? | | -------------------------------------------- | -------------------------- | | 2xx status | No — success. | | 408 Request Timeout or no response in 10s | Yes. | | 5xx status | Yes. | | 429 Too Many Requests | Yes. Honors Retry-After. | | Any other 4xx | No — permanent. | | Connection refused / DNS failure / TLS error | Yes. |

4xx responses other than 408 and 429 are considered permanent. They indicate the payload itself is the problem (signature mismatch, malformed body) and retrying will not help.

Inspecting deliveries

Every attempt — successful or not — is recorded. You can list and inspect deliveries via:

The dashboard surface lives under Developers → Webhooks → Deliveries. Each delivery shows: request payload, signature, your response status and body, and the next retry time.

Manual replay

Aeses lets you replay a delivery on demand — useful after fixing a bug in your endpoint:

A replay creates a new delivery (with its own id) so the original audit trail is preserved.

Designing for retries

Because the same event may arrive more than once, your handler must be idempotent:

  1. Read event.id from the payload.
  2. Check whether you have already processed it (e.g. unique index in your DB).
  3. If new, process the event and persist the event.id.
  4. If duplicate, return 200 OK immediately without re-processing.

This pattern also protects you from at-least-once delivery during planned platform deploys.