Skip to main content
This guide will walk you through installing Resilience and creating your first resilient function.
1

Install the package

Install Resilience using your preferred package manager:
npm install @oldwhisper/resilience
2

Wrap a function with resilience

Import withResilience and wrap any function to add retry logic, timeouts, and more:
import { withResilience } from '@oldwhisper/resilience';

// Your original function
async function fetchData(url: string) {
  const response = await fetch(url);
  if (!response.ok) throw new Error('Request failed');
  return response.json();
}

// Wrap it with resilience features
const resilientFetch = withResilience(fetchData, {
  name: 'fetchData',
  retries: 3,
  timeoutMs: 5000,
  backoff: { type: 'exponential', baseDelayMs: 100, maxDelayMs: 2000 },
  hooks: {
    onAttempt: ({ name, attempt }) => 
      console.log(`${name}: attempt ${attempt}`),
    onRetry: ({ attempt, delayMs, error }) => 
      console.log(`Retrying after ${delayMs}ms:`, error)
  }
});
withResilience always returns an async function, even if your original function is synchronous.
3

Call your resilient function

Use the wrapped function just like the original:
try {
  const data = await resilientFetch('https://api.example.com/data');
  console.log('Success:', data);
} catch (error) {
  console.error('Failed after all retries:', error);
}
The function will automatically:
  • Retry up to 3 times on failure
  • Wait with exponential backoff between retries
  • Timeout after 5 seconds
  • Log attempt and retry information
4

Track metrics with WrapperInit

Use the WrapperInit class to track function calls and collect metrics:
import { WrapperInit } from '@oldwhisper/resilience';

function processOrder(orderId: number, amount: number) {
  return orderId + amount;
}

const metrics = new WrapperInit();
const resilientProcess = metrics.wrap(processOrder, {
  retries: 2,
  timeoutMs: 1000
});

await resilientProcess(100, 250);
await resilientProcess(101, 300);

// Check metrics
console.log('Total calls:', metrics.functionCalls);
console.log('Per-function:', metrics.f_store);
The WrapperInit class automatically tracks function attempts through its built-in hooks, giving you instant observability.

What’s happening under the hood?

When you wrap a function with withResilience:
  1. First attempt: The function executes normally
  2. On failure: If the function throws an error and retries are configured, Resilience catches it
  3. Backoff delay: Waits for the calculated delay (fixed or exponential)
  4. Retry: Attempts the function again
  5. Hooks: Triggers lifecycle hooks at each stage for observability
  6. Circuit breaker: If configured, opens after threshold failures to prevent cascading issues

Common configurations

Simple retry with fixed delay

const fn = withResilience(myFunction, {
  retries: 3,
  backoff: { type: 'fixed', delayMs: 1000 }
});

Exponential backoff with jitter

const fn = withResilience(myFunction, {
  retries: 5,
  backoff: { 
    type: 'exponential', 
    baseDelayMs: 100, 
    maxDelayMs: 5000,
    jitter: true 
  }
});

Circuit breaker for protecting downstream services

const fn = withResilience(myFunction, {
  retries: 3,
  circuitBreaker: {
    failureThreshold: 5,
    resetTimeoutMs: 60000
  },
  hooks: {
    onCircuitOpen: ({ name }) => 
      console.log(`Circuit breaker opened for ${name}`),
    onCircuitClosed: ({ name }) => 
      console.log(`Circuit breaker closed for ${name}`)
  }
});

Next steps

Installation

Detailed installation and setup instructions

Core concepts

Learn about retries, backoff strategies, and circuit breakers

Configuration

Complete configuration reference

API reference

Full API documentation

Build docs developers (and LLMs) love