Overview
Retries give Adal another chance to deliver an accepted webhook when a Destination is temporarily unavailable or returns an error. Adal records the outcome of every attempt and, when the Destination configuration allows it, schedules the next one.
Retries belong to a specific delivery path. When a Server has multiple Destinations, each one has its own attempts, schedule, and final outcome.
Retries make delivery more resilient, but they do not provide exactly-once delivery or eliminate duplicates. Your Destination must be able to process the same request safely more than once.
Successful and failed attempts
Successful attempts
An attempt succeeds when the Destination returns any HTTP status in the 2xx range. Once Adal receives that response, it does not schedule another automatic attempt for the delivery.
A successful delivery status only means that Adal received the expected HTTP response. It does not prove that the application finished processing the webhook, persisted its data, or completed the intended business operation.
Failed attempts
An attempt fails when the Destination returns a status outside the 2xx range or the request cannot be completed. Common causes include:
- the Destination returned a 4xx or 5xx response;
- a network connection could not be established;
- the request timed out;
- a DNS or TLS error occurred;
- Adal CLI could not reach the local service.
A failed result does not necessarily mean the Destination never received the request. The application may have completed its work while the response was lost or arrived after the timeout. A later retry can therefore repeat the same side effect.
Automatic retries
You can configure each Destination to make between 1 and 10 attempts. The configured number includes the initial delivery attempt:
- 1 attempt — one delivery with no automatic retries;
- 2 attempts — the initial attempt and at most one retry;
- 10 attempts — the initial attempt and at most nine retries.
The initial attempt has no additional delay. Adal schedules the next attempt only after the previous one fails. Retries stop when the Destination returns a 2xx response or when the configured attempt limit is reached.
Automatic retries are included in the processing of the original accepted Request and do not consume additional credits.
Retry schedule
After a failed attempt, Adal calculates the delay before the next attempt as follows:
In this formula, n is the number of the next attempt. The delay starts when the previous attempt finishes, not when Adal first accepts the Request.
| Next attempt | Delay after the previous attempt |
|---|---|
| Attempt 2 | 4 minutes |
| Attempt 3 | 9 minutes |
| Attempt 4 | 16 minutes |
| Attempt 5 | 25 minutes |
| Attempt 6 | 36 minutes |
| Attempt 7 | 49 minutes |
| Attempt 8 | 1 hour 4 minutes |
| Attempt 9 | 1 hour 21 minutes |
| Attempt 10 | 1 hour 40 minutes |
| Total scheduled delay | 6 hours 24 minutes |
For example, attempt 2 starts four minutes after attempt 1 finishes. If attempt 2 fails, Adal schedules attempt 3 for another nine minutes later.
The scheduled time is the earliest time at which a retry can begin. The actual delivery may happen later, for example while Adal CLI is disconnected or delivery is temporarily paused.
Waiting for Adal CLI
A disconnected Adal CLI client does not count as a failed attempt. Adal does not start the delivery while the client is offline, so the delivery remains pending and the remaining attempt count is not reduced.
If the scheduled retry time has already passed, the attempt can begin as soon as the CLI reconnects. If that attempt fails, the delay before the next one starts when the failed attempt finishes.
Whether Adal delivers Requests that accumulated while the CLI was offline depends on the Server setting Deliver pending requests on connect:
- when enabled, stored pending Requests are delivered after the CLI reconnects;
- when disabled, the CLI receives only new Requests and the earlier deliveries remain pending.
If the CLI is connected but cannot reach the local service, the delivery has already begun. The failure therefore counts as an attempt.
Independent deliveries
For every accepted Request, Adal creates a separate delivery for each Destination connected to the Server. These delivery paths do not block one another and may finish with different results.
├── Destination A → 2xx → Delivered
├── Destination B → 5xx → Retry scheduled
└── Destination C → CLI disconnected → Pending
A successful delivery to Destination A does not cancel the retry for Destination B. A pending delivery to Destination C does not delay the others. The attempt limit is configured separately for each Destination.
Manual retries, cancellation, and Replay
Manually retry a delivery
A manual retry starts another delivery of an existing Request to one selected Destination. It does not create a new Request or affect delivery to any other Destination.
You can manually retry a failed, cancelled, or already successful delivery. Each manual retry consumes 1 credit.
Cancel a pending delivery
You can cancel a delivery while it is pending. Adal will not run the scheduled automatic attempt after cancellation. An HTTP request that is already in progress cannot be recalled, and cancellation does not affect any other Destination.
Replay a Request
Replay creates a new Request from the stored Request and runs the normal delivery flow for every Destination configured for the Server at that time. The original Request remains unchanged. Replay consumes 1 credit.
| Action | Result | Additional credits |
|---|---|---|
| Automatic retry | Another attempt to one Destination | None |
| Manual retry | A new delivery of an existing Request to one Destination | 1 credit |
| Replay | A new Request delivered to the current Destinations | 1 credit |
Duplicates and idempotency
An automatic or manual retry can deliver the same Request more than once. Replay can also repeat the same provider event as a new Adal Request. Your Destination handler should account for both cases.
You can enable the following header separately for each Destination:
Automatic and manual retries of the same Request use the same key. Replay creates a new Request with a new key. For the key to prevent duplicate work, your application must persist processed values and skip the operation when it sees a key it already knows.
If the webhook provider includes a stable event ID, use it for business-level deduplication. Unlike the Adal key, the provider event ID can identify the same external event after Replay.
- verify the provider signature before processing the request;
- validate the input;
- make the handler idempotent;
- record the stable event ID atomically with the business operation;
- return a 2xx response only after your application has accepted responsibility for processing the event.
The X-Adal-Idempotency header does not turn delivery into an exactly-once operation. Deduplication and safe retry handling remain the responsibility of the Destination.
Delivery history
Open an accepted Request in the Adal dashboard to inspect its deliveries, grouped by Destination. The technical details available for each attempt include:
- the Destination and delivery method;
- the attempt number;
- the date and time of the attempt;
- the current status;
- the HTTP response status, when available;
- the request duration;
- details of a network, DNS, TLS, or other delivery error.
A pending status means the outbound request has not started. The pending entry does not consume an attempt until Adal begins the delivery.
Adal does not store response headers or response bodies from Destinations. Delivery history shows the status, timing, and diagnostic details, but not the complete response content.
Limits and lifecycle
- automatic retries stop at the configured attempt limit;
- a pending delivery remains available only while the source Request is retained;
- after the Request data is deleted, the Request cannot be retried or replayed;
- deleting a Server stops intake, deletes its Destinations, and cancels pending deliveries;
- manual retries and Replay can repeat side effects in the target application.
Retention depends on the plan and Server configuration. When the retention period ends, Adal permanently deletes the Request together with its delivery history and attempt records.
Retries are not a substitute for your own queues, application logs, monitoring, or recovery mechanisms. Your application remains responsible for tracking the business outcome after it receives the Request.
Troubleshooting
No retry was scheduled
Confirm that the Destination did not return a 2xx response and that the configured attempt limit is greater than the number of the last completed attempt. A Destination configured for one attempt does not retry automatically.
An attempt remains pending for a long time
For Adal CLI delivery, check the CLI connection and the Server setting Deliver pending requests on connect. For Direct HTTP, review the scheduled time of the next attempt and the delivery history.
The Destination processed the event twice
Check whether the application persists the idempotency key or stable event ID before performing irreversible work. Remember that a timed-out attempt may have completed the business operation even though Adal never received its response.
Adal shows a successful delivery, but the operation did not happen
Check the logs and state of the target application. A successful delivery confirms a 2xx HTTP response, not the outcome of the application's internal business operation.
Related pages
- Destinations — configure Direct HTTP, Adal CLI, attempt limits, and idempotency keys.
- Servers — learn about request intake, credits, pending delivery, and Replay.
- Adal CLI — connect a local application and troubleshoot delivery.
- Data storage and retention — understand how long Requests and delivery history remain available.
- Plans and limits — review current limits and credit usage.