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

ratewarden

v1.1.0

Published

A zero-config, identity-aware, tier-based rate limiter for Node.js APIs

Downloads

322

Readme

Ratewarden

A zero-config, identity-aware, tier-based rate limiter for Node.js APIs

Stop API abuse without the hassle. ratewarden automatically understands who is making requests and applies intelligent rate limits based on user tiers.

Why Ratewarden?

Most rate limiters are either:

  • Too simple: Only rate limit by IP (breaks for shared networks)
  • Too complex: Require Redis, complex configuration, or 20+ options

ratewarden is the Goldilocks solution:

  • Zero-config: Works out of the box with sensible defaults
  • Identity-aware: Automatically detects users from tokens, headers, or IP
  • Tier-based: Different limits for free, pro, admin users
  • Standard headers: Uses draft IETF RateLimit headers
  • No dependencies: Pure Node.js, no Redis required (but Redis supported for distributed systems)
  • Production-ready: Memory-safe with automatic cleanup
  • Scales up: Optional Redis support for multi-server deployments

Quick Start

Installation

npm install ratewarden

Basic Usage (Zero Config)

const express = require('express');
const ratewarden = require('ratewarden');

const app = express();

// That's it! One line of code.
app.use(ratewarden());

app.get('/api/data', (req, res) => {
  res.json({ message: 'Success!' });
});

app.listen(3000);

Default limits:

  • Authenticated users (token/user ID): 60 requests / minute
  • Anonymous users (IP only): 30 requests / minute

How It Works

Smart Identity Resolution

ratewarden automatically figures out WHO is making the request:

Request → Check Authorization header (JWT/API key) 
       → Check x-user-id header
       → Fall back to IP address

This means:

  • Users with auth tokens get their own limits
  • Shared WiFi (coffee shops, offices) doesn't break your API
  • Anonymous users still get protected

Automatic Tier Assignment

Based on identity, users are automatically assigned tiers:

| Identity Source | Default Tier | Limit | |----------------|--------------|-------| | Authorization token | free | 60/min | | x-user-id header | free | 60/min | | IP address only | guest | 30/min |

Advanced Usage

Custom Tiers

app.use(ratewarden({
  windowMs: 60000, // 1 minute
  tiers: {
    free: 100,
    pro: 1000,
    admin: Infinity
  }
}));

Custom Tier Resolution

Map request to tier based on user data:

app.use(ratewarden({
  resolveTier: (req) => {
    // Assuming you have auth middleware that sets req.user
    if (req.user?.plan === 'premium') return 'pro';
    if (req.user?.isAdmin) return 'admin';
    return 'free';
  }
}));

Custom Identity Key

app.use(ratewarden({
  keyGenerator: (req) => {
    // Rate limit by organization ID instead of user
    return req.user?.organizationId || req.ip;
  }
}));

Custom Error Handling

app.use(ratewarden({
  onLimitReached: (req, res, info) => {
    console.log(`Rate limit hit: ${info.tier}, ${info.current}/${info.limit}`);
    // Still sends 429, but you can log/alert
  }
}));

Route-Specific Limits

// Strict limits on auth endpoints
app.use('/auth', ratewarden({
  tiers: { guest: 5 },
  windowMs: 60000
}));

// Relaxed limits on public API
app.use('/api', ratewarden({
  tiers: { guest: 100 },
  windowMs: 60000
}));

Using with Redis (Distributed Systems)

For multi-server deployments, use Redis to share rate limit state across all servers:

Installation

npm install redis

Basic Setup

const { createClient } = require('redis');
const ratewarden = require('ratewarden');

// Create and connect Redis client
const redisClient = await createClient({
  url: 'redis://localhost:6379'
}).connect();

// Pass redisClient to ratewarden
app.use(ratewarden({
  redisClient
}));

Full Example with Options

const redisClient = await createClient({
  url: process.env.REDIS_URL || 'redis://localhost:6379',
  // Optional: configure connection pooling, timeouts, etc.
}).connect();

app.use(ratewarden({
  windowMs: 60000,
  tiers: {
    guest: 30,
    free: 100,
    pro: 1000
  },
  redisClient,
  redisPrefix: 'myapp:ratelimit:', // Custom key prefix
  onLimitReached: (req, res, info) => {
    console.log(`Rate limit exceeded: ${info.tier}`);
  }
}));

When to Use Redis

Use Redis when:

  • You have multiple app servers (horizontal scaling)
  • You need consistent rate limits across servers
  • You deploy with Docker/Kubernetes (multiple pods)
  • You use serverless/edge functions (shared state needed)

Use in-memory when:

  • Single server deployment
  • Development/testing
  • Simplicity is more important than distributed state

Redis Architecture

Under the hood, ratewarden uses Redis sorted sets for sliding window:

Key: ratewarden:{tier}:{identityKey}
Value: Sorted set of timestamps
Score: Request timestamp (ms)
TTL: 2x windowMs (auto-cleanup)

Example:

ratewarden:free:user123 → ZSET { 
  1678900001234: "1678900001234-abc123",
  1678900005678: "1678900005678-def456"
}

Operations:

  • ZREMRANGEBYSCORE → Remove expired requests
  • ZCARD → Count requests in window
  • ZADD → Add new request
  • Keys auto-expire via EXPIRE command

Benefits:

  • Atomic operations (no race conditions)
  • Distributed consistency
  • Automatic cleanup via TTL
  • O(log N) performance

HTTP Headers

ratewarden follows the IETF RateLimit Headers draft:

On Success (200)

RateLimit-Limit: 60
RateLimit-Remaining: 45
RateLimit-Reset: 1700000123

On Limit Exceeded (429)

HTTP/1.1 429 Too Many Requests
RateLimit-Limit: 60
RateLimit-Remaining: 0
RateLimit-Reset: 1700000123
Retry-After: 24

{
  "error": "Too many requests",
  "message": "Rate limit exceeded for tier 'free'",
  "tier": "free",
  "limit": 60,
  "current": 60,
  "retryAfter": 24
}

Architecture

Algorithm: Sliding Window Counter

Instead of fixed buckets, ratewarden uses a sliding window:

Window = 60 seconds
Limit = 3 requests

Time: 0s    15s   30s   45s   60s
Req:  ✓     ✓     ✓     ✗     ✓
      OK    OK    OK    429   OK (first request expired)

Benefits:

  • More accurate than fixed windows
  • No sudden bursts at window boundaries
  • O(1) check per request

Memory Management

  • Automatic cleanup of expired timestamps
  • Background cleanup runs every minute
  • No memory leaks on long-running servers

Comparison with Other Libraries

| Feature | ratewarden | express-rate-limit | rate-limiter-flexible | |---------|-----------|-------------------|---------------------| | Zero-config | Yes | No (requires config) | No (requires Redis) | | Identity-aware | Yes | No (IP only by default) | Manual setup | | Tier-based | Built-in | Custom code | Custom code | | Dependencies | None (Redis optional) | None | Redis required | | Distributed support | Yes (via Redis) | No | Yes | | Setup time | 30 seconds | 5 minutes | 30+ minutes | | Best for | Small to large APIs, MVPs to Production | Customizable setups | Enterprise only |

Configuration Options

interface RateGuardOptions {
  // Time window in milliseconds (default: 60000)
  windowMs?: number;
  
  // Tier configuration (default: { free: 60, pro: 600, admin: Infinity, guest: 30 })
  tiers?: Record<string, number>;
  
  // Custom tier resolver
  resolveTier?: (req) => string;
  
  // Custom identity key generator
  keyGenerator?: (req) => string;
  
  // Callback when limit is reached
  onLimitReached?: (req, res, info) => void;
  
  // Redis client for distributed rate limiting (optional)
  redisClient?: RedisClientType;
  
  // Redis key prefix (default: 'ratewarden:')
  redisPrefix?: string;
}

Testing

Run tests:

npm test

Expected output:

✓ All tests passed!
Passed: 15
Failed: 0

Use Cases

Perfect for:

  • Hackathon projects: Deploy protection in 30 seconds
  • MVPs and prototypes: No infrastructure overhead
  • SaaS APIs: Built-in tier support
  • Learning projects: Simple, readable code
  • Single-server deployments: Zero-config in-memory storage
  • Multi-server deployments: Optional Redis for distributed state

Not ideal for:

  • Extremely high traffic (>10k req/sec per endpoint per server)
  • Complex sliding window with exact distributed fairness guarantees
  • Sub-millisecond precision requirements

Roadmap

v1.0 (Released)

  • Sliding window algorithm
  • Identity resolution
  • Tier-based limits
  • Standard headers
  • In-memory storage

v1.1 (Current)

  • Redis adapter for distributed systems
  • Store abstraction layer
  • Backward-compatible API

v2.0 (Future)

  • [ ] Prometheus metrics export
  • [ ] Rate limit analytics dashboard
  • [ ] Fastify and Koa adapters
  • [ ] GraphQL query complexity integration

Contributing

Contributions welcome! Please:

  1. Fork the repo
  2. Create a feature branch
  3. Add tests for new features
  4. Submit a PR

License

MIT © Niraj Rajendra Naphade

Philosophy

Batteries included, but removable.

ratewarden makes the 90% use case trivial while still allowing customization for the other 10%.


Made for developers who want protection without complexity