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

web-gatekeeper-js

v1.2.6

Published

Redis based rate limiter and throttler using sliding window and token bucket algorithms

Downloads

2,676

Readme

web-gatekeeper-js

A high-performance, Redis-powered rate limiter and throttler for Node.js applications.
Built for distributed systems, horizontally scalable architectures, and high concurrency environments.

Supports:

  • Sliding Window Counter rate limiting
  • Token Bucket throttling
  • Atomic operations using Lua scripts
  • Distributed environments using Redis
  • Zero race conditions
  • High concurrency handling
  • Express, Fastify, NestJS, Koa, and custom Node.js servers

Features

  • ⚡ Extremely fast Redis-based implementation
  • 🔒 Atomic operations using Redis Lua scripts
  • 🌐 Works across multiple servers/instances
  • 📈 Horizontally scalable
  • 🧠 Supports burst traffic handling
  • 🚫 Prevents race conditions in concurrent environments
  • 🪶 Lightweight and dependency minimal
  • 🔧 Fully configurable
  • 🧵 Safe under heavy parallel requests
  • ♻️ Reusable Redis connections
  • 📦 TypeScript support

Why Redis?

Traditional in-memory rate limiters work only on a single server instance.

That becomes a problem when your application is deployed across:

  • Multiple containers
  • Multiple Node.js processes
  • Kubernetes clusters
  • Load balanced servers
  • Microservices

Redis acts as a centralized shared datastore, allowing every instance of your application to enforce the same limits consistently.

This package uses Redis for:

  • Shared state management
  • Atomic counters
  • Distributed synchronization
  • Fast in-memory performance

Why Lua Scripts?

Redis commands executed separately can lead to race conditions.

Example problem:

Two requests arrive simultaneously.

Both requests:

  1. Read current token count
  2. Both think tokens are available
  3. Both consume tokens
  4. Limit gets bypassed

This package avoids that entirely using Redis Lua scripts.

Lua scripts run atomically inside Redis, meaning:

  • No other Redis command can interrupt execution
  • Read + update operations happen together
  • Concurrent requests remain safe
  • No locks are required

This guarantees correctness even under massive traffic spikes.


Algorithms Used

Sliding Window Counter (Rate Limiter)

Used by RateLimiter.

Tracks requests within a moving time window.

Example:

  • Limit: 100 requests
  • Window: 60 seconds

The limiter continuously tracks requests within the last 60 seconds instead of resetting abruptly like fixed window algorithms.

Benefits

  • Smoother limiting
  • More accurate than fixed windows
  • Prevents sudden request bursts at window boundaries
  • Better user experience

Token Bucket (Throttler)

Used by Throttler.

Tokens refill gradually over time.

Example:

  • Bucket size: 10
  • Refill rate: 2 tokens/sec

If the bucket has tokens available, requests are allowed immediately.

If not:

  • Requests are delayed/rejected
  • Burst traffic is controlled gracefully

Benefits

  • Handles traffic spikes efficiently
  • Allows short bursts
  • Smooth request flow
  • Ideal for APIs and real-time systems

Installation

npm install gatekeeper-js ioredis

Quick Start

Rate Limiter Example

import { RateLimiter } from 'gatekeeper-js'
import Redis from 'ioredis'

const redis = new Redis()

const limiter = new RateLimiter({
  redisClient : redis,
  windowSize  : 60000,
  limit       : 100,
  maxToken    : 10,
  refillRate  : 2
})

app.use(async (req, res, next) => {
  const result = await limiter.consume(req.ip)

  if (!result.allowed) {
    return res.status(429).json({
      error: result.reason
    })
  }

  next()
})

Throttler Example

import { Throttler } from 'gatekeeper-js'
import Redis from 'ioredis'

const redis = new Redis()

const throttler = new Throttler({
  redisClient : redis,
  refillRate  : 2,
  maxWait     : 5000
})

app.use(async (req, res, next) => {
  const result = await throttler.consume(req.ip)

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

  next()
})

API

RateLimiter

Constructor

new RateLimiter(options)

Options

| Option | Type | Required | Description | |---|---|---|---| | redisClient | Redis | Yes | ioredis client instance | | windowSize | number | Yes | Time window in milliseconds | | limit | number | Yes | Maximum requests allowed per window | | maxToken | number | No | Maximum burst capacity | | refillRate | number | No | Token refill rate per second |


consume(key)

Consumes one request for a given identifier.

const result = await limiter.consume('user-id')

Response

{
  allowed: true,
  remaining: 42,
  resetTime: 1716200000000
}

Response Fields

| Field | Description | |---|---| | allowed | Whether request is allowed | | remaining | Remaining requests/tokens | | resetTime | Unix timestamp when limit resets | | reason | Rejection reason if blocked |


Throttler

Constructor

new Throttler(options)

Options

| Option | Type | Required | Description | |---|---|---|---| | redisClient | Redis | Yes | ioredis client instance | | refillRate | number | Yes | Tokens added per second | | maxWait | number | No | Maximum wait time before rejection |


consume(key)

const result = await throttler.consume('user-id')

Response

{
  allowed: true,
  retryAfter: 0
}

Scalability

This package is designed for distributed systems.

Because Redis stores the state centrally:

  • Multiple Node.js instances share the same limits
  • Limits remain consistent across deployments
  • Works seamlessly behind load balancers
  • Suitable for microservices and Kubernetes

Example architecture:

Client Requests
       ↓
Load Balancer
       ↓
 ┌─────────────┐
 │ Node App 1  │
 ├─────────────┤
 │ Node App 2  │
 ├─────────────┤
 │ Node App 3  │
 └─────────────┘
       ↓
     Redis

All application instances communicate with the same Redis server.


Concurrency Safety

This package is safe under heavy concurrent traffic.

Redis Lua scripts ensure:

  • Atomic execution
  • No partial updates
  • No inconsistent counters
  • No race conditions

Even if thousands of requests arrive simultaneously, limits remain accurate.


Performance

Redis operations are extremely fast because Redis stores data in memory.

The package is optimized to:

  • Minimize Redis calls
  • Use atomic Lua execution
  • Reduce network overhead
  • Handle high throughput efficiently

Suitable for:

  • Public APIs
  • Authentication systems
  • Login protection
  • Payment APIs
  • WebSocket gateways
  • Real-time applications

Redis Compatibility

Compatible with:

  • Redis 6+
  • Redis 7+
  • Redis Cluster
  • Redis Cloud providers

Framework Support

Works with any Node.js framework:

  • Express
  • Fastify
  • NestJS
  • Koa
  • Hono
  • Native HTTP servers

Error Handling

Example:

try {
  const result = await limiter.consume(req.ip)

  if (!result.allowed) {
    return res.status(429).json({
      error: result.reason
    })
  }

  next()
} catch (error) {
  console.error(error)

  return res.status(500).json({
    error: 'Internal Server Error'
  })
}

Best Practices

Use Stable Keys

Good examples:

req.ip
user.id
apiKey

Avoid random or frequently changing keys.


Reuse Redis Connections

Create one shared Redis client instance and reuse it across the application.

const redis = new Redis()

Configure Reasonable Limits

| Use Case | Suggested Limit | |---|---| | Login API | 5 requests/min | | Public API | 100 requests/min | | OTP Verification | 3 requests/5 min |


License

ISC License

Permission to use, modify, and distribute this software for any purpose with or without fee is hereby granted.

See the LICENSE file for full details.


Contributing

Contributions are welcome.

Feel free to:

  • Open issues
  • Suggest improvements
  • Submit pull requests

Roadmap

Planned features:

  • Redis Cluster optimizations
  • Sliding log algorithm
  • Fixed window limiter
  • Rate limit headers
  • Automatic retries
  • Memory fallback store
  • Metrics integration

Author

Built for modern distributed Node.js applications using Redis and Lua for correctness, scalability, and performance.