---
id: flow--retry-plugin
title: "Retry"
summary: "Calls the components behind `Output`; when they fail with an exception, the record is put into a retry list and re-sent later, up to `MaxRetries` times. If it still fails, the record goes to the `MaxRetries` pin."
audience: user
keywords: "input, output, maxretries, strategy, deltamilliseconds"
---
# Retry

Calls the components behind `Output`; when they fail with an exception, the record is put into a retry list and re-sent later, up to `MaxRetries` times. If it still fails, the record goes to the `MaxRetries` pin.

## Pins

| Pin | Kind | Types | Description |
|---|---|---|---|
| Input | input | any | Record to process. |
| Output | output | same as input | The branch that is tried and retried. |
| MaxRetries | output | same as input | Called with the original record and metadata when all retries failed. |

## Configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `Strategy` | dropdown: `1` Fixed, `2` Progressive | `1` | How the wait time before a retry is computed. |
| `MaxRetries` | integer (0-1024) | `3` | Number of retries after the first failed attempt. |
| `DeltaMilliseconds` | integer | `3000` | Base wait time in ms. Values below 500 are raised to 500 (with a warning). |

## Behaviour

- Every record is first sent to `Output` synchronously. If it succeeds, nothing else happens.
- If the `Output` branch throws an exception (an error not handled downstream, e.g. by Try catch), the exception is **not** passed back to the caller. The record (with its metadata) is stored in the retry list, keyed by the record id, and `Execute` returns normally.
- A background timer checks the list every 100 ms and re-sends records whose retry time has passed. A successful retry removes the record from the list.
- Wait times: Fixed = `DeltaMilliseconds` before every retry. Progressive = `(retry number + 1) × DeltaMilliseconds`, so with `2000`: 4000, 6000, 8000 ms, ...
- With `MaxRetries` = `3` the record is tried 4 times (1 + 3 retries); after the last failure `MaxRetries` is called and the record is removed. Exceptions in the `MaxRetries` branch are ignored.
- Cancellation (`TaskCanceledException`) and `UnRecoverableFlowException` are not retried.
- The status message shows the size of the retry list ("Retry queue - Empty" or the count).

## Notes

- Retries run asynchronously on the timer thread. The component that sent the record sees success after the first failure, so upstream error handling (Try catch, HTTP error responses) is not triggered.
- `MaxRetries` = `0` still performs one retry before calling the `MaxRetries` pin.
- The retry list is kept in memory only; pending retries are lost when the flow stops.
- If an `UnRecoverableFlowException` occurs during a retry, the timer is not restarted and no further retries are processed until the flow restarts (code defect). Normally such an exception stops the flow anyway.
- Records with the same record id share one retry entry.
- The retry loop uses the configuration from flow start; expressions in `Strategy` / `MaxRetries` / `DeltaMilliseconds` are evaluated per record only for the first failure.

## Example

```json
{ "Strategy": 2, "MaxRetries": 5, "DeltaMilliseconds": 2000 }
```

Queue → **Retry** → Http client ; `MaxRetries` → Log / Database writer (dead letters)
