> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hookstream.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Retry Strategies

Configure exponential, linear, or fixed backoff for delivery retries.

When a delivery returns a non-2xx status or throws a network error, hookstream schedules a retry on the destination's [DeliveryScheduler](/concepts/delivery-pipeline) Durable Object. Retries are alarm-driven, which means they survive Worker restarts and always run once the alarm fires.

## Compare the three strategies

| Strategy | When to use | Default intervals |
| --- | --- | --- |
| `exponential` | Default choice. Gives a failing endpoint room to recover while keeping the total retry window bounded. | `[30, 300, 1800, 7200, 86400]` seconds (30s → 24h) |
| `linear` | Predictable, evenly-growing delays. Good for monitoring dashboards where you want retries spaced by a fixed cadence. | `intervals[0] × attemptNumber` |
| `fixed` | Idempotent endpoints that just need the same nudge every N seconds. | `intervals[0]` every time |

All three read from the same `retry_intervals` array on the destination. Exponential uses the whole array as a lookup table; linear and fixed only read `intervals[0]`.

## How the math works

**Exponential**

Attempt N uses `intervals[min(N - 1, intervals.length - 1)]`. With the default array, retries fire at 30s, 5m, 30m, 2h, and 24h. If `retry_max_attempts` exceeds the array length, the final interval is reused.
  **Linear**

Delay = `intervals[0] × attemptNumber`. Default base is 30 seconds, so retries fire at 30s, 60s, 90s, 120s, 150s.
  **Fixed**

Delay = `intervals[0]` on every attempt. Default is 30 seconds.

Delays are deterministic — there is no built-in jitter. If your destination cannot tolerate a thundering herd, stagger delivery with per-connection filters or spread destinations across retry schedules.

## Configure retries

**Decide on a strategy**

Start with exponential unless you have a strong reason not to. The default intervals are a good balance for most APIs.
  **Create or update the destination**

Set `retry_backoff_type`, `retry_max_attempts`, and `retry_intervals` on the destination:

    ```bash
    curl -X POST https://hookstream.io/v1/destinations \
      -H "X-API-Key: $HOOKSTREAM_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "My API",
        "type": "http",
        "config": { "url": "https://api.example.com/webhook" },
        "retry_max_attempts": 5,
        "retry_backoff_type": "exponential",
        "retry_intervals": [30, 300, 1800, 7200, 86400]
      }'
    ```
  **Watch retries in the dashboard**

Each delivery attempt is logged individually on the Events and Delivery Attempts pages, with status code, latency, and the retry number. When all attempts are exhausted the event moves to the [dead letter queue](/guides/dead-letter-queue).

## Troubleshooting

**Retries aren't firing after a failure**

Check the destination's [circuit breaker](/guides/circuit-breaker) state — if it is open, new deliveries are queued until the cooldown probe succeeds. Also confirm `retry_max_attempts` is greater than 0 and that the delivery actually failed (2xx responses are considered successful).
  **Retries are happening too fast / too slow**

Exponential uses the `retry_intervals` array directly — edit it to change the schedule. Linear and fixed only read the first element, so adjust `intervals[0]`.
  **My destination is rate limited**

Either increase the intervals so retries spread out, or switch to `fixed` backoff with a delay that matches your destination's rate limit window.

## Next Steps

**[Delivery Pipeline](/concepts/delivery-pipeline)**

How ingest, filters, transforms, and delivery attempts fit together.
  **[Dead Letter Queue](/guides/dead-letter-queue)**

What happens after the last retry is exhausted.