npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mukulchavan/resilient-http

v1.0.0

Published

A smart wrapper around fetch/axios that adds controlled retries, backoff strategies, circuit breaker pattern, and failure metrics

Readme

resilient-http

A smart wrapper around fetch and axios that adds controlled retries, backoff strategies, circuit breaker pattern, and failure metrics - all with minimal code changes.

🎯 The Problem

APIs fail all the time:

  • Temporary network glitches
  • 502 / 503 / 504 from backend
  • Cold starts
  • Rate limiting
  • Partial outages

What teams usually do:

try {
  await axios.get('/api/data');
} catch (e) {
  await axios.get('/api/data'); // naive retry
}

Problems:

  • ❌ No backoff → thundering herd
  • ❌ Infinite retries
  • ❌ No failure tracking
  • ❌ Can bring down entire system

✨ What This Library Does

A smart wrapper that adds:

  • ✅ Controlled retries
  • ✅ Backoff strategies (fixed, linear, exponential, jitter)
  • ✅ Circuit breaker pattern
  • ✅ Failure metrics

All with one line of code.

🔌 What Is a Circuit Breaker?

Think of it like MCB (Miniature Circuit Breaker) in your house.

| State | Meaning | |-------|---------| | Closed | API working → requests allowed | | Open | API failing → requests blocked | | Half-Open | Try few requests to test recovery |

Why it matters:

  • Prevents hitting already failing services
  • Saves latency & infra cost
  • Improves user experience

📦 Installation

npm install resilient-http

🚀 Usage

Fetch Example

import { resilientFetch } from 'resilient-http';

const response = await resilientFetch('/api/orders', {
  retries: 3,
  backoff: 'exponential',
  retryOn: [502, 503, 504],
  circuitBreaker: {
    failureThreshold: 5,
    resetTimeout: 30000
  }
});

const data = await response.json();

Axios Example

import { createResilientAxios } from 'resilient-http';

const api = createResilientAxios({
  retries: 2,
  backoff: 'linear'
});

// Use it like regular axios
const response = await api.get('/products');

With Metrics Hooks

import { resilientFetch } from 'resilient-http';

const response = await resilientFetch('/api/data', {
  retries: 3,
  backoff: 'exponential',
  onRetry: ({ url, attempt, error }) => {
    console.log(`Retrying ${url} (attempt ${attempt})`);
  },
  onOpen: (url) => {
    console.log(`Circuit breaker opened for ${url}`);
  },
  onClose: (url) => {
    console.log(`Circuit breaker closed for ${url}`);
  }
});

⚙️ Configuration

Retry Configuration

interface RetryConfig {
  retries?: number;              // Number of retries (default: 3)
  backoff?: 'fixed' | 'linear' | 'exponential' | 'jitter';  // Backoff strategy (default: 'exponential')
  retryOn?: number[];            // HTTP status codes to retry on (default: [502, 503, 504])
  initialDelay?: number;         // Initial delay in ms (default: 500)
  maxDelay?: number;             // Maximum delay in ms (default: 30000)
  timeout?: number;              // Request timeout in ms (default: 0 = no timeout)
}

Circuit Breaker Configuration

interface CircuitBreakerConfig {
  failureThreshold?: number;     // Errors before opening circuit (default: 5)
  successThreshold?: number;     // Successes to close circuit in half-open (default: 2)
  resetTimeout?: number;         // Wait before half-open in ms (default: 30000)
}

Backoff Strategies

| Type | Example Delays | |------|----------------| | Fixed | 500ms, 500ms, 500ms | | Linear | 500ms, 1000ms, 1500ms | | Exponential | 500ms, 1000ms, 2000ms, 4000ms | | Jitter | Randomized exponential (reduces thundering herd) |

🔄 Retry Logic

Retry Conditions

  • Network errors (connection failures)
  • HTTP status codes in retryOn list
  • Timeout errors

Backoff Calculation

The library automatically calculates delays based on the selected strategy:

  • Fixed: Always uses initialDelay
  • Linear: initialDelay * attempt
  • Exponential: initialDelay * 2^(attempt - 1)
  • Jitter: Exponential with random variation (30% jitter)

🔌 Circuit Breaker Logic

How It Works

  1. Track failures per endpoint
  2. If failures ≥ failureThresholdOPEN
  3. Block calls immediately (fast fail)
  4. After resetTimeoutHALF-OPEN
  5. Test with limited calls
  6. If successThreshold successes → CLOSED
  7. If any failure → OPEN again

Example Configuration

{
  failureThreshold: 5,     // 5 errors before opening circuit
  successThreshold: 2,     // 2 successes to close circuit
  resetTimeout: 30000      // wait 30s before half-open
}

📊 Metrics Hooks

Track retries and circuit breaker state changes:

{
  onRetry: ({ url, attempt, error, statusCode }) => {
    // Called on each retry attempt
  },
  onOpen: (url) => {
    // Called when circuit breaker opens
  },
  onClose: (url) => {
    // Called when circuit breaker closes
  }
}

🏗️ Architecture

Components

  1. Request Wrapper - Wraps fetch/axios calls, handles retries
  2. Retry Engine - Determines if retry is allowed, calculates delay
  3. Circuit Store - Maintains per-endpoint state (memory-based)
  4. Metrics Hook - Callbacks for monitoring

📝 TypeScript Support

Full TypeScript support with type definitions included:

import { resilientFetch, ResilientConfig } from 'resilient-http';

const config: ResilientConfig = {
  retries: 3,
  backoff: 'exponential',
  circuitBreaker: {
    failureThreshold: 5,
    resetTimeout: 30000
  }
};

const response = await resilientFetch('/api/data', config);

🧪 Testing

Running Tests

# Install dependencies
npm install

# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests with coverage
npm run test:coverage

Test Structure

The test suite includes:

  • ✅ Backoff strategy tests (fixed, linear, exponential, jitter)
  • ✅ Circuit breaker state transitions
  • ✅ Retry logic and conditions
  • ✅ Fetch wrapper integration
  • ✅ Axios wrapper integration
  • ✅ Metrics hooks verification

Manual Testing

You can also test the library manually using the provided test script:

# Build the project first
npm run build

# Then run manual tests (requires ts-node)
npx ts-node test-manual.ts

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

MIT