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

ratelimitly-client

v2.0.2

Published

Ratelimitly JavaScript client - centralized rate limiting and latency-based load shedding over UDP

Readme

RateLimitly JavaScript Client (ratelimitly-client)

CI npm version Node.js Version Zero Dependencies License: MIT

Official Node.js client library for Ratelimitly — high-performance, centralized distributed rate limiting and latency-based load shedding over a low-latency UDP wire protocol.

What is Ratelimitly?

Ratelimitly is rate limiting and load shedding as a service. Your application asks a nearby Ratelimitly server for an admit/deny decision over a single UDP round trip: rate limits enforce per-account and per-resource quotas, and latency guards shed traffic automatically when a protected resource (a database, an upstream service) slows down. Servers are discovered through DNS SRV records tied to your API key, so there is nothing to configure but the key.


Key Highlights

  • ⚡ Sub-Millisecond UDP Wire Protocol: Microsecond-speed binary serialization over UDP without TCP connection overhead or Redis roundtrips.
  • 🛡️ Zero Dependencies: Pure Node.js implementation built strictly on standard library built-ins (crypto, dgram, dns, events, buffer).
  • 🔄 Continuous Sliding Window: Smooth, real-time distributed admission control without fixed-window boundary burst resets.
  • 🔒 AES-256-GCM Encryption & Authentication: Authenticated Associated Data (AAD) binds clear headers and encrypts PDUs with unique CSPRNG nonces per datagram.
  • 🎯 Multi-Resource Atomic Checks: Evaluate global, tenant, user, and endpoint quotas together in a single atomic network roundtrip.
  • ⏱️ Latency Guards & Load Shedding: Protect downstream databases and microservices by shedding traffic automatically when latency exceeds defined thresholds.
  • 🌐 High Availability & DNS Discovery: Dynamic SRV discovery (_ratelimitly._udp.<domain>) and configurable retry gap schedules (fixed, linear, exponential).
  • 📘 Full TypeScript Support: First-class TypeScript declarations (index.d.ts and api_key_codec.d.ts) included out of the box.

Architecture Overview

Node.js Application
      |  checkRateLimit()
      v
RClient (ratelimitly-client)
      |  zero-config DNS SRV discovery
      |  (_ratelimitly._udp.c-<keyId>.p0.ratelimitly.com)
      v
Ratelimitly Node A / Node B          <- UDP wire protocol, AES-256-GCM
      |
      v
Admit / Deny decision  ->  back to your application

Installation

npm install ratelimitly-client

Requirements: Node.js >= 20.0.0


Quick Start

const { createClient, ResourceRequest } = require('ratelimitly-client');

// 1. Initialize client with your RateLimitly Bech32 API key
// (DNS discovery domain is derived automatically from the key)
const client = createClient(process.env.RATELIMITLY_AUTH_KEY);

// 2. Define resource limit (e.g. 100 requests per 60 seconds)
const resources = [
  new ResourceRequest('api_traffic', 60000, 100, 1)
];

// 3. Check rate limit
client.checkRateLimit(resources, (err, result) => {
  if (err) {
    console.error('Communication error:', err.message);
    return;
  }

  if (result.success) {
    console.log('✅ Request admitted by RateLimitly');
  } else {
    console.log('⛔ Rate limit exceeded! Tokens deficit:', result.resourceResults[0].tokensDeficit);
  }
});

Core Features & Usage Patterns

1. Multi-Resource Atomic Checks

Evaluate multiple limits in a single datagram. If any quota is exceeded, the request is denied as an atomic unit:

const resources = [
  new ResourceRequest('global_traffic', 60000, 10000, 1), // 10,000 req/min
  new ResourceRequest(`user:${userId}`, 1000, 20, 1),       // 20 req/sec
  new ResourceRequest(`org:${orgId}:burst`, 10000, 100, 1)  // 100 req/10s
];

client.checkRateLimit(resources, (err, result) => {
  if (result && result.success) {
    // All quotas passed
  }
});

2. Latency Guards & Dynamic Load Shedding

Protect downstream services (e.g. databases, external payment APIs) from brownouts:

const { LatencyGuard, ServiceLatencyBlock } = require('ratelimitly-client');

const guards = [
  new LatencyGuard({
    latencyTrackerName: 'primary_postgres',
    thresholdMs: 150,       // Max acceptable downstream latency
    ttlMs: 300000,          // Sample window TTL (5 minutes)
    maxSamples: 32,         // Max moving window samples
    minSampleThreshold: 5   // Minimum samples before guard activates
  })
];

client.checkRateLimit(resources, guards, 'checkout.api', async (err, result) => {
  if (!result || !result.success) {
    // Rate limit or latency guard tripped
    return;
  }

  // Execute database query
  const start = Date.now();
  await executeDatabaseQuery();
  const elapsed = Date.now() - start;

  // Asynchronously report downstream latency back to RateLimitly
  client.reportLatency([
    new ServiceLatencyBlock({
      latencyTrackerName: 'primary_postgres',
      observedLatency: elapsed,
      ttlMs: 300000
    })
  ]);
});

3. Async / Await and Promise Wrapper

Convert callback methods to clean async/await functions:

function checkRateLimitAsync(client, resources, guards = [], metricsLabel = null) {
  return new Promise((resolve, reject) => {
    client.checkRateLimit(resources, guards, metricsLabel, (err, result) => {
      if (err) return reject(err);
      resolve(result);
    });
  });
}

// Usage in Express / Fastify / Koa / NestJS:
async function handleRequest(req, res) {
  const result = await checkRateLimitAsync(client, [
    new ResourceRequest(`ip:${req.ip}`, 1000, 10, 1)
  ]);

  if (!result.success) {
    return res.status(429).json({ error: 'Too Many Requests' });
  }

  return res.json({ status: 'ok' });
}

4. High Availability & Custom Retry Policies

Configure custom retry policies with fixed, linear, or exponential backoff:

const { RequestPolicy, HaSchedule, createClient } = require('ratelimitly-client');

const haPolicy = new RequestPolicy({
  unitMs: 20,                                // Base scheduling quantum (ms)
  replayCount: 2,                            // Max replay rounds
  replayGap: HaSchedule.exponential(1, 2, 4), // Exponential growth: 1 -> 2 -> 4 units
  finalReceiveUnits: 1,                      // Tail receive interval
  completionDelivery: true                   // Broadcast result to missing servers
});

const client = createClient(process.env.RATELIMITLY_AUTH_KEY, null, {
  requestPolicy: haPolicy,
  dnsRefreshIntervalS: 300 // DNS SRV refresh interval
});

API Reference

createClient(authKey, [dnsName], [options])

Creates and initializes an RClient instance.

  • authKey (string): RateLimitly Bech32 API key (rl-aes1..., rl-cookie1..., rl-none1...).
  • dnsName (string, optional): Override tenant discovery domain (defaults to c-${keyId}.p0.ratelimitly.com).
  • options (object, optional):
    • requestPolicy (RequestPolicy): Custom HA retry/timeout policy.
    • dnsRefreshIntervalS (number): DNS SRV cache refresh interval in seconds (default: 300).
    • steeringFeedback (boolean): Enable server port steering affinity (default: false).

RClient Methods

  • checkRateLimit(resources, [guards], [metricsLabel], callback): Evaluates rate quotas and latency guards.
  • reportLatency(serviceLatencyBlocks, callback): Asynchronously reports observed service latencies.
  • getServerStats(): Returns active server endpoints, stability records, and DNS refresh timestamps.

ResourceRequest(bucketName, windowSizeMs, rateLimit, [tokensRequested])

  • bucketName (string): Logical name or identifier for the rate bucket.
  • windowSizeMs (number): Sliding window length in milliseconds (e.g. 1000, 60000).
  • rateLimit (number): Maximum allowed tokens within the window.
  • tokensRequested (number, default: 1): Tokens requested by this operation.

LatencyGuard(options)

  • latencyTrackerName (string): Identifier of the downstream service to track.
  • thresholdMs (number): Maximum allowed latency before shedding requests.
  • ttlMs (number): Expiration TTL for tracked latency samples.
  • maxSamples (number, default: 32): Maximum moving samples.
  • minSampleThreshold (number, default: 5): Minimum samples required before activation.

Bech32 API Key Codec

The library includes a standalone encoder/decoder for RateLimitly's Bech32 key format:

const { decodeApiKey, encodeApiKey, bytesToHex } = require('ratelimitly-client/api_key_codec');

const decoded = decodeApiKey('rl-aes1qx2kk...');
console.log({
  authMethod: decoded.authMethod, // 'aes', 'cookie', or 'none'
  keyId: decoded.keyId,           // BigInt (e.g. 4265246494029998997n)
  quotas: decoded.quotas          // Embedded quota limits
});

Examples Directory

Explore runnable examples in the examples/ directory:


Security

Please review SECURITY.md for our threat model, AES-256-GCM authentication details, and vulnerability disclosure process.


Contributing

Contributions are welcome! Please read CONTRIBUTING.md for development setup and testing instructions.


License

This project is licensed under the MIT License.