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

@prakarsh123/rate-limiter

v1.0.0

Published

Production-ready API Rate Limiting & Quota Management - Use as a library or standalone service

Downloads

9

Readme

Rate Limiter Service

Production-ready API Rate Limiting & Quota Management Service built with Node.js/TypeScript, Fastify, and Redis.

🚀 Features

  • Multiple Rate Limiting Algorithms

    • Token Bucket (smooth rate limiting with burst capacity)
    • Fixed Window (simple time-based limiting)
    • Sliding Window (accurate, prevents boundary issues)
  • Dual Interface Support

    • REST API (Fastify)
    • gRPC (coming soon)
  • Distributed & Scalable

    • Redis-backed distributed state
    • Works across multiple service instances
    • Atomic operations via Lua scripts
  • Granular Control

    • Per-user rate limiting
    • Per-API-endpoint limiting
    • Per-IP limiting
    • Composite keys (user+endpoint, IP+endpoint)
  • Smart Notifications

    • Webhook alerts at configurable thresholds
    • Retry logic with exponential backoff
    • HMAC signatures for security
  • Production Ready

    • Docker deployment
    • TypeScript client SDK
    • OpenAPI/Swagger documentation
    • Health checks and monitoring

📦 Quick Start

Using Docker Compose (Recommended)

# Clone the repository
git clone <repo-url>
cd rate-limiter-service

# Start the service
docker-compose -f docker/docker-compose.yml up -d

# Check health
curl http://localhost:3000/v1/health

Local Development

# Install dependencies
npm install

# Copy environment file
cp .env.example .env

# Start Redis (required)
docker run -d -p 6379:6379 redis:7-alpine

# Run in development mode
npm run dev

# Or build and run
npm run build
npm start

📖 API Documentation

Once the service is running, visit:

  • Swagger UI: http://localhost:3000/docs
  • API Base: http://localhost:3000

🔧 Usage Examples

Basic Rate Limiting

import { RateLimiterClient } from "./client/rest-client";

const client = new RateLimiterClient("http://localhost:3000");

// Check rate limit
const result = await client.check({
  key: "user:123",
  endpoint: "/api/users",
  algorithm: "token_bucket",
  limit: 100,
  window: 3600, // 1 hour in seconds
});

if (result.allowed) {
  console.log("Request allowed!");
  console.log(`Remaining: ${result.remaining}/${result.limit}`);
} else {
  console.log(`Rate limited! Retry after ${result.retryAfter}s`);
}

Using Rules

// Create a reusable rule
const rule = await client.createRule({
  name: "API Users Endpoint",
  algorithm: "token_bucket",
  limit: 1000,
  window: 3600,
  keys: [{ type: "user", value: "*" }],
  webhookUrl: "https://example.com/webhooks/rate-limit",
  thresholds: [80, 90, 100],
});

// Use the rule
const result = await client.check({
  key: "user:456",
  ruleId: rule.id,
});

Express Middleware

import express from "express";
import { RateLimiterClient } from "./client/rest-client";

const app = express();
const rateLimiter = new RateLimiterClient("http://localhost:3000");

app.use(async (req, res, next) => {
  try {
    const result = await rateLimiter.check({
      key: `user:${req.user?.id || req.ip}`,
      endpoint: req.path,
      algorithm: "token_bucket",
      limit: 100,
      window: 3600,
    });

    res.set("X-RateLimit-Limit", result.limit);
    res.set("X-RateLimit-Remaining", result.remaining);
    res.set("X-RateLimit-Reset", result.resetAt);

    if (!result.allowed) {
      return res.status(429).json({
        error: "Too many requests",
        retryAfter: result.retryAfter,
      });
    }

    next();
  } catch (error) {
    next(); // Fail open on errors
  }
});

🎯 Algorithm Comparison

| Algorithm | Pros | Cons | Best For | | ------------------ | --------------------------------------------- | ------------------------------------ | ------------------------------------- | | Token Bucket | Smooth rate limiting, allows bursts, flexible | More complex, slightly higher memory | APIs with variable load, file uploads | | Fixed Window | Simple, fast, low memory | Boundary issues, can be gamed | High throughput, simple limits | | Sliding Window | Most accurate, no boundary issues | Higher memory, more complex | Critical operations, fraud prevention |

🔄 Switching Algorithms

Algorithms can be switched at multiple levels:

1. Per-Rule Configuration

await client.createRule({
  algorithm: "token_bucket", // or 'fixed_window', 'sliding_window'
  // ...
});

2. Runtime Selection

await client.check({
  key: "user:123",
  algorithm: "sliding_window", // Override per request
  limit: 100,
  window: 3600,
});

3. Dynamic Based on User Tier

const algorithm = tier === "free" ? "fixed_window" : "token_bucket";
await client.check({ key, algorithm, limit, window });

🔔 Webhook Notifications

Configure webhooks to receive notifications when rate limits are approached:

await client.createRule({
  name: "Payment API",
  algorithm: "sliding_window",
  limit: 100,
  window: 3600,
  webhookUrl: "https://your-app.com/webhooks/rate-limit",
  thresholds: [80, 90, 100], // Notify at 80%, 90%, 100%
});

Webhook payload:

{
  "key": "user:123",
  "endpoint": "/api/payment",
  "limit": 100,
  "currentUsage": 85,
  "threshold": 80,
  "timestamp": "2026-01-11T02:30:00Z",
  "message": "Rate limit 80% threshold reached for user:123"
}

🏗️ Architecture

┌─────────────────────────────────────────────────┐
│           Your Application                      │
│  ┌──────────┐      ┌──────────┐                │
│  │ API GW 1 │      │ API GW 2 │                │
│  └────┬─────┘      └────┬─────┘                │
│       │                 │                       │
│       └────────┬────────┘                       │
│                │                                │
│                ▼                                │
│    ┌───────────────────────┐                   │
│    │  Rate Limiter Service │◄──── REST/gRPC    │
│    │   (This Service)      │                   │
│    └───────────┬───────────┘                   │
│                │                                │
│                ▼                                │
│         ┌──────────┐                            │
│         │  Redis   │  (Distributed State)      │
│         └──────────┘                            │
└─────────────────────────────────────────────────┘

🛠️ Configuration

Environment variables (.env):

# Server
NODE_ENV=development
REST_PORT=3000
GRPC_PORT=50051

# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DB=0

# Webhooks
WEBHOOK_TIMEOUT=5000
WEBHOOK_MAX_RETRIES=3
WEBHOOK_RETRY_DELAY=1000

# Logging
LOG_LEVEL=info

📊 Monitoring

Health Check

curl http://localhost:3000/v1/health

Service Info

curl http://localhost:3000/v1/info

🧪 Testing

# Run all tests
npm test

# Run integration tests
npm run test:integration

# Watch mode
npm run test:watch

📝 API Endpoints

Rate Limiting

  • POST /v1/check - Check if request is allowed

Rule Management

  • POST /v1/rules - Create rule
  • GET /v1/rules - List all rules
  • GET /v1/rules/:id - Get rule by ID
  • PUT /v1/rules/:id - Update rule
  • DELETE /v1/rules/:id - Delete rule

Health

  • GET /v1/health - Health check
  • GET /v1/info - Service information

🚢 Deployment

Docker

docker build -f docker/Dockerfile -t rate-limiter .
docker run -p 3000:3000 -e REDIS_HOST=redis rate-limiter

Docker Compose

docker-compose -f docker/docker-compose.yml up -d

Kubernetes (coming soon)

📄 License

MIT

🤝 Contributing

Contributions welcome! Please read our contributing guidelines.

💬 Support