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

ezthrottle

v1.1.1

Published

Node.js SDK for EZThrottle - The API Dam for rate-limited services

Downloads

9

Readme

EZThrottle Node.js SDK

The API Dam for rate-limited services. Queue and execute HTTP requests with smart retry logic, multi-region racing, and webhook delivery.

Installation

npm install ezthrottle

Quick Start

const { EZThrottle, Step, StepType } = require('ezthrottle');

const client = new EZThrottle({ apiKey: 'your_api_key' });

// Simple job submission
const result = await new Step(client)
  .url('https://api.example.com/endpoint')
  .method('POST')
  .type(StepType.PERFORMANCE)
  .webhooks([{ url: 'https://your-app.com/webhook' }])
  .execute();

console.log(`Job ID: ${result.job_id}`);

Step Types

StepType.PERFORMANCE (Server-side execution)

Submit jobs to EZThrottle for distributed execution with multi-region racing and webhook delivery.

await new Step(client)
  .url('https://api.stripe.com/charges')
  .type(StepType.PERFORMANCE)
  .webhooks([{ url: 'https://app.com/webhook' }])
  .regions(['iad', 'lax', 'ord'])  // Multi-region racing
  .executionMode('race')  // First completion wins
  .execute();

StepType.FRUGAL (Client-side first)

Execute locally first, only forward to EZThrottle on specific error codes. Saves money!

await new Step(client)
  .url('https://api.example.com')
  .type(StepType.FRUGAL)
  .fallbackOnError([429, 500, 503])  // Forward to EZThrottle on these codes
  .execute();

Idempotent Key Strategies

Critical concept: Idempotent keys prevent duplicate job execution. Choose the right strategy for your use case.

IdempotentStrategy.HASH (Default)

Backend generates deterministic hash of (url, method, body, customer_id). Prevents duplicates.

Use when:

  • Payment processing (don't charge twice!)
  • Critical operations (create user, send notification)
  • You want automatic deduplication

Example:

const { IdempotentStrategy } = require('ezthrottle');

// Prevents duplicate charges - same request = rejected as duplicate
await new Step(client)
  .url('https://api.stripe.com/charges')
  .body(JSON.stringify({ amount: 1000, currency: 'usd' }))
  .idempotentStrategy(IdempotentStrategy.HASH)  // Default
  .execute();

IdempotentStrategy.UNIQUE

SDK generates unique UUID per request. Allows duplicates.

Use when:

  • Polling endpoints (same URL, different data each time)
  • Webhooks (want to send every time)
  • Scheduled jobs (run every minute/hour)
  • GET requests that return changing data

Example:

// Poll API every minute - each request gets unique UUID
setInterval(async () => {
  await new Step(client)
    .url('https://api.example.com/status')
    .idempotentStrategy(IdempotentStrategy.UNIQUE)  // New UUID each time
    .execute();
}, 60000);

Workflow Chaining

Chain steps together with .onSuccess(), .onFailure(), and .fallback():

// Analytics step (cheap)
const analytics = new Step(client)
  .url('https://analytics.com/track')
  .type(StepType.FRUGAL);

// Notification (fast, distributed)
const notification = new Step(client)
  .url('https://notify.com')
  .type(StepType.PERFORMANCE)
  .webhooks([{ url: 'https://app.com/webhook' }])
  .regions(['iad', 'lax'])
  .onSuccess(analytics);

// Primary API call (cheap local execution)
await new Step(client)
  .url('https://api.example.com')
  .type(StepType.FRUGAL)
  .fallbackOnError([429, 500])
  .onSuccess(notification)
  .execute();

Fallback Chains

Handle failures with automatic fallback execution:

const backupApi = new Step().url('https://backup-api.com');

await new Step(client)
  .url('https://primary-api.com')
  .fallback(backupApi, { triggerOnError: [500, 502, 503] })
  .execute();

Multi-Region Racing

Submit jobs to multiple regions, fastest wins:

await new Step(client)
  .url('https://api.example.com')
  .regions(['iad', 'lax', 'ord'])  // Try all 3 regions
  .regionPolicy('fallback')  // Auto-route if region down
  .executionMode('race')  // First completion wins
  .webhooks([{ url: 'https://app.com/webhook' }])
  .execute();

Webhook Fanout (Multiple Webhooks)

Deliver job results to multiple services simultaneously:

await new Step(client)
  .url('https://api.stripe.com/charges')
  .method('POST')
  .webhooks([
    // Primary webhook (must succeed)
    { url: 'https://app.com/payment-complete', has_quorum_vote: true },

    // Analytics webhook (optional)
    { url: 'https://analytics.com/track', has_quorum_vote: false },

    // Notification service (must succeed)
    { url: 'https://notify.com/alert', has_quorum_vote: true },

    // Multi-region webhook racing
    { url: 'https://backup.com/webhook', regions: ['iad', 'lax'], has_quorum_vote: true }
  ])
  .webhookQuorum(2)  // At least 2 webhooks with has_quorum_vote=true must succeed
  .execute();

Retry Policies

Customize retry behavior:

await new Step(client)
  .url('https://api.example.com')
  .retryPolicy({
    max_retries: 5,
    max_reroutes: 3,
    retry_codes: [429, 503],  // Retry in same region
    reroute_codes: [500, 502, 504]  // Try different region
  })
  .execute();

Production Ready ✅

This SDK is production-ready with working examples validated in CI on every push.

Reference Implementation: test-app/

The test-app/ directory contains real, working code you can learn from. Not toy examples - this is production code we run in automated tests against live EZThrottle backend.

Multi-Region Racing (test-app/app.js:104-122)

await new Step(client)
  .url('https://httpbin.org/delay/1')
  .type(StepType.PERFORMANCE)
  .webhooks([{ url: `${APP_URL}/webhook` }])
  .regions(['iad', 'lax', 'ord'])  // Race across 3 regions
  .executionMode('race')  // First completion wins
  .execute();

Idempotent HASH (Deduplication) (test-app/app.js:181-203)

// Same request twice = same job_id (deduplicated)
await new Step(client)
  .url(`https://httpbin.org/get?run=${runId}`)
  .idempotentStrategy(IdempotentStrategy.HASH)
  .execute();

Fallback Chain (test-app/app.js:125-154)

await new Step(client)
  .url('https://httpbin.org/status/500')
  .fallback(
    new Step().url('https://httpbin.org/status/200'),
    { triggerOnError: [500, 502, 503] }
  )
  .execute();

On-Success Workflow (test-app/app.js:157-178)

await new Step(client)
  .url('https://httpbin.org/status/200')
  .onSuccess(
    new Step().url('https://httpbin.org/delay/1')
  )
  .execute();

FRUGAL Local Execution (test-app/app.js:247-260)

await new Step(client)
  .url('https://httpbin.org/status/200')
  .type(StepType.FRUGAL)
  .execute();

Validated in CI:

  • ✅ GitHub Actions runs these examples against live backend on every push
  • ✅ 7 integration tests covering all SDK features
  • ✅ Proves the code actually works, not just documentation

Legacy API (Deprecated)

For backward compatibility, the old queueRequest() method is still available:

await client.queueRequest({
  url: 'https://api.example.com',
  webhookUrl: 'https://your-app.com/webhook',  // Note: singular
  method: 'POST'
});

Prefer the new Step builder API for all new code!

Environment Variables

EZTHROTTLE_API_KEY=your_api_key_here

License

MIT