Retries

Automatic retries for transient provider failures, with a configurable backoff curve and clear rules for what is and isn't retried.

retries retries transient failures automatically. Pass a number as shorthand for { max }, or { max, backoff } to control the wait between attempts. Set it on the constructor as a default and override it per call.

const files = new Files({
  adapter: s3({ bucket: "uploads" }),
  retries: { max: 3, backoff: ({ attempt }) => attempt * 500 },
});

// Opt a single write out of retries.
await files.upload("avatars/abc.png", file, { retries: 0 });

What is retried

Only Provider failures — transient things like network blips, throttling, and 5xx responses. The classified codes are returned to you immediately, because retrying them can't help:

  • NotFound, Unauthorized, and Conflict are deterministic — the same call fails the same way.
  • Aborts and timeouts are never retried; retrying a cancelled call would defeat the cancellation.
  • Uploads from a ReadableStream are never retried, because a consumed stream can't be safely replayed. Buffered bodies (File, Blob, ArrayBuffer, Uint8Array, string) retry normally.

See Errors for how codes are assigned.

Backoff

The default backoff is exponential — 100 * 2 ** (attempt - 1) ms, so 100ms, 200ms, 400ms, … — capped at 30 seconds, with no jitter. attempt is 1 for the first retry after the initial failure.

For high-fanout callers, supply your own backoff({ attempt, error }) to add jitter or a different curve. A caller-supplied function is used verbatim — no cap is applied, so the ceiling is yours to set.

// Exponential with full jitter, still capped at 30s.
new Files({
  adapter: s3({ bucket: "uploads" }),
  retries: {
    max: 5,
    backoff: ({ attempt }) =>
      Math.random() * Math.min(30_000, 100 * 2 ** (attempt - 1)),
  },
});

Wire onRetry to observe each scheduled attempt — its attempt, delayMs, and the triggering error.

Bulk operations

retries is a single-key option; the array forms don't take it. They surface per-key failures in their errors[] result instead, so you can inspect or re-drive only the keys that failed. See Errors.

On this page