tiny-pretry
v1.0.0
Published
Retry async functions with exponential backoff. Same API as p-retry, ships ESM + CJS with zero dependencies.
Maintainers
Readme
tiny-retry
Retry async functions with exponential backoff. Same API as p-retry, but ships both ESM and CJS with zero dependencies.
import { pRetry } from "tiny-pretry";
const data = await pRetry(
() => fetch("https://api.example.com/data").then((r) => r.json()),
{ retries: 3 },
);~800 bytes gzipped. Zero dependencies. Replaces p-retry without the ESM-only headache.

Demo built with remotion-readme-kit
Install
npm install tiny-pretryUsage
import { pRetry } from "tiny-pretry";
const result = await pRetry(
async (attemptNumber) => {
console.log(`Attempt ${attemptNumber}`);
const res = await fetch("https://api.example.com");
if (!res.ok) throw new Error(res.statusText);
return res.json();
},
{ retries: 5 },
);Stop retrying early
import { pRetry, AbortError } from "tiny-pretry";
await pRetry(
async () => {
const res = await fetch("https://api.example.com");
if (res.status === 401) {
throw new AbortError("Not authorized, retrying won't help");
}
return res.json();
},
{ retries: 5 },
);Track failed attempts
await pRetry(doWork, {
retries: 5,
onFailedAttempt: (error) => {
console.log(
`Attempt ${error.attemptNumber} failed. ${error.retriesLeft} retries left.`,
);
},
});Cancel with AbortSignal
const controller = new AbortController();
setTimeout(() => controller.abort(), 10000);
await pRetry(unreliableCall, {
retries: 10,
signal: controller.signal,
});Differences from p-retry
p-retry v6+ is ESM-only. If you require("p-retry") in a CommonJS project, you get ERR_REQUIRE_ESM. tiny-retry works with both import and require().
| | p-retry | tiny-retry |
| ------------ | --------------------------- | ------------ |
| CJS support | v5 only (v6+ ESM-only) | ESM + CJS |
| Dependencies | retry, is-network-error | 0 |
| TypeScript | separate @types | native |
| Export | default | named |
Migrating from p-retry
- import pRetry from "p-retry";
+ import { pRetry } from "tiny-pretry";One line. Everything else stays the same.
API
pRetry(fn, options?)
Retries fn until it succeeds or retries are exhausted.
fn(attemptNumber)- function to retry (attempt starts at 1)options.retries- max retries (default:10)options.factor- exponential factor (default:2)options.minTimeout- initial delay in ms (default:1000)options.maxTimeout- max delay cap in ms (default:Infinity)options.randomize- add jitter to delays (default:false)options.signal-AbortSignalfor cancellationoptions.onFailedAttempt(error)- called after each failure
AbortError
Throw new AbortError(message) or new AbortError(error) inside fn to stop retrying immediately.
FailedAttemptError
The error passed to onFailedAttempt has two extra properties:
attemptNumber- which attempt just failed (1-based)retriesLeft- how many retries remain
The tiny-* family
Drop-in replacements for sindresorhus async utilities. All ship ESM + CJS with zero dependencies.
| Package | Replaces | What it does | | ------------------------------------------------------ | -------------------- | ------------------------------ | | tiny-limit | p-limit | Concurrency limiter | | tiny-map | p-map | Concurrent map with order | | tiny-retry | p-retry | Retry with exponential backoff | | tiny-queue | p-queue | Priority task queue | | tiny-ms | ms | Parse/format durations | | tiny-escape | escape-string-regexp | Escape regex chars |
Want all async utilities in one import? Use tiny-pasync.
Author
If this saved you from ERR_REQUIRE_ESM, star the repo or open an issue if something breaks.
