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

# Retries

> Which requests BundleUp retries automatically, how long it waits, and how to change the retry count.

Providers fail occasionally: a timeout, a `503` during a deploy, a `429` when you’ve hit their limit. For requests that are safe to repeat, BundleUp retries automatically so a brief blip doesn’t reach your code.

Retries apply to the **Proxy** and the **Unified API**. [MCP](/docs/guides/mcp/proxy-mcp) requests are never retried; your MCP client decides what to do.

## When a request is retried

```mermaid theme={null}
flowchart TD
    A[Provider response] --> B{2xx?}
    B -->|Yes| OK[Return it]
    B -->|No| C{"Method is GET,<br/>HEAD or OPTIONS?"}
    C -->|No| RET[Return the failure]
    C -->|Yes| D{"Status is 408, 429,<br/>502, 503 or 504?"}
    D -->|No| RET
    D -->|Yes| E{Retries left?}
    E -->|No| RET
    E -->|Yes| F{"Provider sent<br/>Retry-After?"}
    F -->|Yes| G["Wait Retry-After<br/>(at most 15 s)"]
    F -->|No| H["Wait 250 ms × 2^attempt<br/>± 20% jitter"]
    G --> RETRY[Send again]
    H --> RETRY
    RETRY --> A
```

A request is retried only when **all** of these are true:

1. **The method is idempotent:** `GET`, `HEAD` or `OPTIONS`. `POST`, `PUT`, `PATCH` and `DELETE` are never retried, because repeating them could create or change something twice.
2. **The failure is transient:** `408 Request Timeout`, `429 Too Many Requests`, `502 Bad Gateway`, `503 Service Unavailable` or `504 Gateway Timeout`. A provider that doesn’t answer within the [timeout](/docs/guides/proxy/making-requests#timeouts) counts as `408`; a provider BundleUp can’t reach at all counts as `502`.
3. **There are retries left.** By default, 3 retries: up to 4 attempts in total.

Any other response (including `400`, `401`, `403`, `404` and `500`) is returned straight away.

## How long BundleUp waits

* If the provider sent a **`Retry-After`** header (seconds or an HTTP date), BundleUp waits that long, **capped at 15 seconds**.
* Otherwise it backs off exponentially: about **250 ms, 500 ms, 1 s, 2 s, 4 s** for attempts 1 to 5, each with ±20% random jitter so many clients don’t retry in lockstep.

If every attempt fails, you get the **last** response from the provider.

## Changing the retry count

Send `BU-Max-Retries` to set the maximum number of **retries** (not attempts) for one request:

```bash theme={null}
curl https://proxy.bundleup.io/user/repos \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "BU-Connection-Id: conn_abc123" \
  -H "BU-Max-Retries: 0"
```

| Value | Behaviour |
| - | - |
| Not sent | 3 retries (up to 4 attempts) |
| `0` | No retries. One attempt. |
| `1` to `5` | That many retries. |
| Above `5` | Capped at 5 retries (up to 6 attempts). |

The header only affects that request. It doesn’t make non-idempotent methods retryable.

**Turn retries off** (`0`) when you have your own retry logic, or when a fast failure is more useful than a late success, such as in a user-facing request with a tight deadline.

**Turn retries up** for background jobs against providers known to be flaky.

## Retries and usage

Each retry is a real call to the provider and is [logged and counted](/docs/concepts/requests#what-counts-toward-usage) as a request. A `GET` that succeeds on the third attempt counts as three requests. Retries also count toward the connection’s [rate limit](/docs/guides/proxy/rate-limits) at the provider, though not toward BundleUp’s.

## Retrying writes yourself

Because writes are never retried automatically, handle their failures in your code. If the provider supports idempotency keys (for example, an `Idempotency-Key` header), send one. The Proxy forwards it unchanged, so you can retry the write safely.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.