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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@bernierllc/retry-policy

v0.1.6

Published

Atomic retry policy utilities with exponential backoff and jitter

Readme

@bernierllc/retry-policy

Atomic retry policy utilities with exponential backoff and jitter support.

Overview

@bernierllc/retry-policy provides atomic utilities for implementing retry logic with configurable backoff strategies and jitter. This package is designed to be a core building block that can be used by higher-level retry managers and services.

Features

  • Multiple backoff strategies: Exponential, linear, and constant backoff
  • Configurable jitter: Full, equal, decorrelated, and no jitter options
  • Custom retry conditions: Flexible error evaluation logic
  • Type-safe API: Full TypeScript support with strict typing
  • Zero dependencies: Pure functions with no external dependencies
  • Comprehensive testing: 95%+ test coverage

Installation

npm install @bernierllc/retry-policy

Quick Start

import { RetryPolicy, createRetryPolicy } from '@bernierllc/retry-policy';

// Create a retry policy with default settings
const policy = new RetryPolicy();

// Evaluate if an operation should be retried
const result = policy.evaluateRetry(1, new Error('Network error'));
console.log(result);
// {
//   shouldRetry: true,
//   delay: 2000,
//   attempt: 1,
//   isFinalAttempt: false
// }

API Reference

RetryPolicy Class

The main class for managing retry policies.

Constructor

new RetryPolicy(options?: Partial<RetryPolicyOptions>, backoffConfig?: Partial<BackoffConfig>)

Methods

  • evaluateRetry(attempt: number, error: any): RetryPolicyResult
  • calculateDelay(attempt: number): number
  • getOptions(): Required<RetryPolicyOptions>
  • getBackoffConfig(): BackoffConfig
  • updateOptions(options: Partial<RetryPolicyOptions>): void
  • updateBackoffConfig(config: Partial<BackoffConfig>): void

Utility Functions

  • createRetryPolicy(options?, backoffConfig?): RetryPolicy
  • calculateRetryDelay(attempt, options?, backoffConfig?): number
  • shouldRetry(attempt, error, options?): boolean

Usage Examples

Basic Usage

import { RetryPolicy } from '@bernierllc/retry-policy';

const policy = new RetryPolicy({
  maxRetries: 3,
  initialDelayMs: 1000,
  shouldRetry: (error) => error.code === 'NETWORK_ERROR'
});

// In your retry loop
for (let attempt = 0; attempt <= 3; attempt++) {
  try {
    const result = await someOperation();
    break; // Success, exit retry loop
  } catch (error) {
    const retryResult = policy.evaluateRetry(attempt, error);
    
    if (!retryResult.shouldRetry) {
      throw error; // Don't retry, re-throw error
    }
    
    // Wait before next attempt
    await new Promise(resolve => setTimeout(resolve, retryResult.delay));
  }
}

Custom Backoff Strategy

import { RetryPolicy } from '@bernierllc/retry-policy';

const policy = new RetryPolicy(
  { maxRetries: 5 },
  {
    type: 'exponential',
    baseDelay: 500,
    factor: 3,
    maxDelay: 10000,
    jitter: {
      type: 'full',
      factor: 0.1
    }
  }
);

// This will use exponential backoff with full jitter
const delay = policy.calculateDelay(2); // ~4500ms with jitter

Different Backoff Types

import { RetryPolicy } from '@bernierllc/retry-policy';

// Exponential backoff (default)
const exponential = new RetryPolicy(undefined, {
  type: 'exponential',
  baseDelay: 1000,
  factor: 2
});
// Delays: 1000ms, 2000ms, 4000ms, 8000ms...

// Linear backoff
const linear = new RetryPolicy(undefined, {
  type: 'linear',
  baseDelay: 1000
});
// Delays: 1000ms, 2000ms, 3000ms, 4000ms...

// Constant backoff
const constant = new RetryPolicy(undefined, {
  type: 'constant',
  baseDelay: 1000
});
// Delays: 1000ms, 1000ms, 1000ms, 1000ms...

Jitter Types

import { RetryPolicy } from '@bernierllc/retry-policy';

// Full jitter: random value between 0 and delay
const fullJitter = new RetryPolicy(undefined, {
  jitter: { type: 'full', factor: 0.1 }
});

// Equal jitter: random value between delay/2 and delay
const equalJitter = new RetryPolicy(undefined, {
  jitter: { type: 'equal', factor: 0.1 }
});

// Decorrelated jitter: random value between delay and delay * 3
const decorrelatedJitter = new RetryPolicy(undefined, {
  jitter: { type: 'decorrelated', factor: 0.1 }
});

// No jitter: exact delay values
const noJitter = new RetryPolicy(undefined, {
  jitter: { type: 'none' }
});

Custom Retry Conditions

import { RetryPolicy } from '@bernierllc/retry-policy';

const policy = new RetryPolicy({
  maxRetries: 5,
  shouldRetry: (error) => {
    // Only retry on network errors or 5xx server errors
    if (error.code === 'NETWORK_ERROR') return true;
    if (error.status >= 500 && error.status < 600) return true;
    return false;
  },
  onRetry: (attempt, delay, error) => {
    console.log(`Retry attempt ${attempt} after ${delay}ms due to:`, error.message);
  },
  onFailure: (error) => {
    console.log('All retry attempts exhausted:', error.message);
  }
});

Configuration

RetryPolicyOptions

interface RetryPolicyOptions {
  maxRetries: number;           // Maximum number of retry attempts
  initialDelayMs: number;       // Initial delay in milliseconds
  maxDelayMs?: number;          // Maximum delay in milliseconds
  backoffFactor?: number;       // Exponential backoff factor
  jitter?: boolean;             // Whether to apply jitter
  shouldRetry?: (error: any) => boolean;  // Custom retry condition
  onRetry?: (attempt: number, delay: number, error: any) => void;  // Retry callback
  onFailure?: (error: any) => void;  // Failure callback
}

BackoffConfig

interface BackoffConfig {
  type: 'exponential' | 'linear' | 'constant';  // Backoff strategy
  baseDelay: number;           // Base delay in milliseconds
  maxDelay: number;            // Maximum delay in milliseconds
  factor?: number;             // Backoff factor for exponential
  jitter?: JitterConfig;       // Jitter configuration
}

JitterConfig

interface JitterConfig {
  type: 'none' | 'full' | 'equal' | 'decorrelated';  // Jitter type
  factor?: number;             // Jitter factor (0-1)
}

Default Values

const DEFAULT_RETRY_OPTIONS = {
  maxRetries: 5,
  initialDelayMs: 1000,
  maxDelayMs: 30000,
  backoffFactor: 2,
  jitter: true,
  shouldRetry: () => true,
  onRetry: () => {},
  onFailure: () => {}
};

const DEFAULT_BACKOFF_CONFIG = {
  type: 'exponential',
  baseDelay: 1000,
  maxDelay: 30000,
  factor: 2,
  jitter: { type: 'full', factor: 0.1 }
};

Integration Status

Logger Integration

Status: not-applicable

This is a pure utility core package with no dependencies. Logging is handled by consuming packages. Does not require @bernierllc/logger integration.

Docs-Suite Integration

Status: ready

Complete API documentation with TypeScript types and examples available for documentation suite integration.

NeverHub Integration

Status: not-applicable

Pure utility package with no runtime dependencies. NeverHub integration is handled at the service-level packages that consume this utility. Does not require @bernierllc/neverhub-adapter integration.

Security

This package has zero runtime dependencies and uses only pure TypeScript functions. Security considerations:

  • No External Dependencies: All retry logic is implemented internally with no external packages at runtime
  • Type Safety: Strict TypeScript typing prevents common runtime errors
  • No Network Calls: Pure computational functions with no I/O operations
  • No Secret Storage: Does not handle or store any sensitive data
  • Audit Clean: npm audit shows no vulnerabilities (zero dependencies)

For security concerns, please open an issue in the repository.

Testing

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Run tests in watch mode
npm run test:watch

Contributing

This package follows the Bernier LLC development standards:

  • TypeScript strict mode - All code must pass strict type checking
  • Comprehensive testing - 95%+ test coverage required
  • Documentation - All public APIs must be documented
  • Code style - Follow project ESLint configuration

License

ISC License - see LICENSE file for details.

Related Packages

  • @bernierllc/retry-state - Retry state management and persistence
  • @bernierllc/retry-metrics - Retry performance metrics collection
  • @bernierllc/retry-manager - High-level retry orchestration service