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

limiter.js

v1.0.5

Published

limiter.js is a Node.js/TypeScript library that provides simple Rate limiter protection for Express applications. It tracks requests per IP address and enforces rate limits within a sliding time window. If an IP exceeds the allowed requests, limiter.js ca

Downloads

19

Readme

Limiter.js

limiter.js is a Node.js/TypeScript library that provides simple Rate limiter protection for Express applications. It tracks requests per IP address and enforces rate limits within a sliding time window. If an IP exceeds the allowed requests, limiter.js can temporarily ban that IP and even permanently ban repeat offenders based on configurable thresholds. The core component is the Detector class (see src/core/Detector.ts in source) which maintains a map of IP trackers and applies a RateLimiter policy. You integrate it as an Express middleware, where it inspects each incoming request and blocks excess traffic, returning HTTP 429 when limits are exceeded.

Features

  • IP-based rate limiting: Counts requests per IP in a configurable time window (windowMs).
  • Temporary bans: Automatically bans an IP for banDurationMs once it exceeds maxHitsAllowed within the window.
  • Permanent bans: If an IP repeatedly exceeds limits (meeting permanentBanThreshold), it can be permanently banned.
  • Express middleware: Integrates easily via expressGuardMiddleware(detector) in any Express app.
  • Logging of IP status: Provides methods to log current hit counts and ban status for each tracked IP to the console (useful for monitoring).
  • Configurable: All thresholds (time window, max hits, ban duration, etc.) are adjustable through a simple Config object.

Installation

You can install the library using npm:

npm install limiter.js@latest

Quick Start

import { expressGuardMiddleware, Detector } from "limiter.js";
import express from "express";

const app = express();
const port = 3000;

const detector = new Detector({
  windowMs: 60 * 1000, // 1 minute time window
  maxHitsAllowed: 10, // 10 requests per minute
  banDurationMs: 10 * 1000, // 10 seconds ban duration
  permanentBanThreshold: 30, // 30 requests for permanent ban
});

app.use(expressGuardMiddleware(detector));

app.get("/", (req, res) => {
  res.send("Hello, world!");
});

app.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`);
});

Configuration Examples

Basic API Rate Limiting

// Basic setup for a public API - allows 100 requests per hour
const apiDetector = new Detector({
  windowMs: 60 * 60 * 1000, // 1 hour
  maxHitsAllowed: 100,
  banDurationMs: 30 * 60 * 1000, // 30 minutes ban
  permanentBanThreshold: 500, // Permanent ban after 500 requests in window
});

app.use('/api', expressGuardMiddleware(apiDetector));

Strict Authentication Endpoint Protection

// Strict limits for sensitive endpoints like login
const authDetector = new Detector({
  windowMs: 15 * 60 * 1000, // 15 minutes
  maxHitsAllowed: 5, // Only 5 login attempts per 15 minutes
  banDurationMs: 60 * 60 * 1000, // 1 hour ban
  permanentBanThreshold: 20, // Permanent ban after 20 attempts
});

app.use('/auth/login', expressGuardMiddleware(authDetector));
app.use('/auth/register', expressGuardMiddleware(authDetector));

Development Mode (Lenient)

// Lenient settings for development environment
const devDetector = new Detector({
  windowMs: 60 * 1000, // 1 minute
  maxHitsAllowed: 1000, // Very high limit for development
  banDurationMs: 5 * 1000, // Short 5-second ban
  // No permanent ban threshold for development
});

if (process.env.NODE_ENV === 'development') {
  app.use(expressGuardMiddleware(devDetector));
}

Production Web App

// Balanced settings for a production web application
const webDetector = new Detector({
  windowMs: 10 * 60 * 1000, // 10 minutes
  maxHitsAllowed: 200, // 200 requests per 10 minutes
  banDurationMs: 20 * 60 * 1000, // 20 minutes ban
  permanentBanThreshold: 1000, // Permanent ban threshold
});

app.use(expressGuardMiddleware(webDetector));

Advanced Usage

Multiple Rate Limiters for Different Routes

import { expressGuardMiddleware, Detector } from "limiter.js";
import express from "express";

const app = express();

// General API rate limiter
const generalDetector = new Detector({
  windowMs: 60 * 1000,
  maxHitsAllowed: 60,
  banDurationMs: 60 * 1000,
  permanentBanThreshold: 300,
});

// Strict rate limiter for sensitive operations
const strictDetector = new Detector({
  windowMs: 5 * 60 * 1000,
  maxHitsAllowed: 10,
  banDurationMs: 30 * 60 * 1000,
  permanentBanThreshold: 50,
});

// File upload rate limiter
const uploadDetector = new Detector({
  windowMs: 60 * 1000,
  maxHitsAllowed: 5,
  banDurationMs: 10 * 60 * 1000,
  permanentBanThreshold: 20,
});

// Apply different limiters to different routes
app.use('/api/general', expressGuardMiddleware(generalDetector));
app.use('/api/auth', expressGuardMiddleware(strictDetector));
app.use('/api/upload', expressGuardMiddleware(uploadDetector));

app.get('/api/general/users', (req, res) => {
  res.json({ users: [] });
});

app.post('/api/auth/login', (req, res) => {
  res.json({ token: 'example-token' });
});

app.post('/api/upload', (req, res) => {
  res.json({ message: 'File uploaded successfully' });
});

app.listen(3000, () => {
  console.log('Server running with multiple rate limiters');
});

Monitoring and Logging

import { expressGuardMiddleware, Detector } from "limiter.js";
import express from "express";

const app = express();

const detector = new Detector({
  windowMs: 60 * 1000,
  maxHitsAllowed: 100,
  banDurationMs: 5 * 60 * 1000,
  permanentBanThreshold: 500,
});

app.use(expressGuardMiddleware(detector));

// Monitoring endpoint (protect this in production!)
app.get('/admin/rate-limit-status', (req, res) => {
  console.log('=== Rate Limiter Status ===');
  detector.logStatus(); // Logs all tracked IPs
  res.json({ message: 'Check console for rate limiter status' });
});

// Check specific IP status
app.get('/admin/ip-status/:ip', (req, res) => {
  const ip = req.params.ip;
  console.log(`=== Status for IP: ${ip} ===`);
  detector.logIPStatus(ip);
  res.json({ message: `Check console for IP ${ip} status` });
});

// Periodic logging (every 5 minutes)
setInterval(() => {
  console.log('=== Periodic Rate Limiter Status ===');
  detector.logStatus();
}, 5 * 60 * 1000);

app.listen(3000);

Custom Error Handling

import { expressGuardMiddleware, Detector } from "limiter.js";
import express from "express";

const app = express();

const detector = new Detector({
  windowMs: 60 * 1000,
  maxHitsAllowed: 50,
  banDurationMs: 10 * 60 * 1000,
  permanentBanThreshold: 200,
});

// Custom middleware that adds additional handling
app.use((req, res, next) => {
  const result = detector.handleRequest(req.ip || req.connection.remoteAddress || 'unknown');
  
  if (result.blocked) {
    // Log the blocked request
    console.log(`Blocked request from ${req.ip}: ${result.reason}`);
    
    // Custom response based on ban type
    if (result.reason?.includes('permanently banned')) {
      return res.status(429).json({
        error: 'Permanently Banned',
        message: 'Your IP has been permanently banned due to repeated violations.',
        retryAfter: null
      });
    } else {
      return res.status(429).json({
        error: 'Rate Limited',
        message: 'Too many requests. Please try again later.',
        retryAfter: '10 minutes'
      });
    }
  }
  
  next();
});

app.get('/', (req, res) => {
  res.json({ message: 'API is working!' });
});

app.listen(3000);

Environment-based Configuration

import { expressGuardMiddleware, Detector } from "limiter.js";
import express from "express";

const app = express();

// Configuration based on environment
const getDetectorConfig = () => {
  const env = process.env.NODE_ENV || 'development';
  
  switch (env) {
    case 'production':
      return {
        windowMs: 15 * 60 * 1000, // 15 minutes
        maxHitsAllowed: 100,
        banDurationMs: 60 * 60 * 1000, // 1 hour
        permanentBanThreshold: 500,
      };
    
    case 'staging':
      return {
        windowMs: 5 * 60 * 1000, // 5 minutes
        maxHitsAllowed: 200,
        banDurationMs: 30 * 60 * 1000, // 30 minutes
        permanentBanThreshold: 1000,
      };
    
    case 'development':
    default:
      return {
        windowMs: 60 * 1000, // 1 minute
        maxHitsAllowed: 1000,
        banDurationMs: 10 * 1000, // 10 seconds
        permanentBanThreshold: 5000,
      };
  }
};

const detector = new Detector(getDetectorConfig());

app.use(expressGuardMiddleware(detector));

app.get('/', (req, res) => {
  res.json({ 
    message: `Hello from ${process.env.NODE_ENV} environment!`,
    rateLimitConfig: getDetectorConfig()
  });
});

app.listen(3000, () => {
  console.log(`Server running in ${process.env.NODE_ENV} mode`);
});

Integration with Express Router

import { expressGuardMiddleware, Detector } from "limiter.js";
import express from "express";

const app = express();
const router = express.Router();

// Create different detectors for different route groups
const publicApiDetector = new Detector({
  windowMs: 60 * 1000,
  maxHitsAllowed: 100,
  banDurationMs: 5 * 60 * 1000,
  permanentBanThreshold: 500,
});

const adminApiDetector = new Detector({
  windowMs: 60 * 1000,
  maxHitsAllowed: 20,
  banDurationMs: 30 * 60 * 1000,
  permanentBanThreshold: 100,
});

// Public API routes with generous limits
router.use('/public', expressGuardMiddleware(publicApiDetector));
router.get('/public/status', (req, res) => {
  res.json({ status: 'OK', timestamp: new Date() });
});

router.get('/public/info', (req, res) => {
  res.json({ info: 'This is a public endpoint' });
});

// Admin routes with strict limits
router.use('/admin', expressGuardMiddleware(adminApiDetector));
router.get('/admin/users', (req, res) => {
  res.json({ users: ['admin', 'user1', 'user2'] });
});

router.post('/admin/settings', (req, res) => {
  res.json({ message: 'Settings updated' });
});

app.use('/api', router);

app.listen(3000, () => {
  console.log('Server running with route-specific rate limiting');
});

Configuration Reference

The Detector is configured via an object with the following properties:

| Property | Type | Required | Description | |----------|------|----------|-------------| | windowMs | number | Yes | Time window for counting requests, in milliseconds | | maxHitsAllowed | number | Yes | Maximum allowed requests per IP within one window | | banDurationMs | number | Yes | Duration of a temporary ban (in ms) when the rate is exceeded | | permanentBanThreshold | number | No | If provided, an IP reaching this hit count in the window will be permanently banned |

Common Configuration Patterns

  • Lenient (Development): windowMs: 60000, maxHitsAllowed: 1000, banDurationMs: 5000
  • Moderate (Web App): windowMs: 600000, maxHitsAllowed: 200, banDurationMs: 1200000
  • Strict (API): windowMs: 3600000, maxHitsAllowed: 100, banDurationMs: 1800000
  • Very Strict (Auth): windowMs: 900000, maxHitsAllowed: 5, banDurationMs: 3600000

API Methods

Detector Methods

  • handleRequest(ip: string): Manually check if an IP should be blocked
  • logStatus(): Log status of all tracked IPs to console
  • logIPStatus(ip: string): Log status of a specific IP to console

Best Practices

  1. Environment-specific configs: Use different limits for development, staging, and production
  2. Route-specific limits: Apply stricter limits to sensitive endpoints (auth, admin)
  3. Monitor regularly: Use the logging methods to monitor rate limiting effectiveness
  4. Gradual enforcement: Start with lenient limits and tighten based on traffic patterns
  5. Consider user experience: Don't make limits too strict for legitimate users
  6. Permanent ban carefully: Use permanent bans sparingly and only for clear abuse patterns

Contributing

Contributions, bug reports, and feature requests are welcome! Please fork the repository and open an issue or pull request on GitHub. Ensure your code follows the existing style and includes any relevant tests.

License

This project is licensed under the ISC License.

Contact