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

redlimit

v2.0.3

Published

Redis rate limiting with fixed window, sliding window, and token bucket algorithms

Readme

redlimit

Redis rate limiting with fixed window, sliding window, and token bucket algorithms

npm install redlimit redis
# or: npm install redlimit ioredis

Quick Start

import { Limiter } from 'redlimit'
import { createClient } from 'redis'

const redis = createClient()
await redis.connect()

const limiter = new Limiter({
  redis,
  algorithm: 'sliding-window',
  limit: 10,
  window: '30s',
})

const { success, headers } = await limiter.limit('user_123')

if (!success) {
  return res.status(429).set(headers).end()
}

Or with ioredis:

import { Limiter } from 'redlimit'
import Redis from 'ioredis'

const redis = new Redis()

const limiter = new Limiter({
  redis,
  algorithm: 'sliding-window',
  limit: 10,
  window: '30s',
})

Algorithms

All algorithms run as atomic Lua scripts inside Redis.

// Fixed window - counts requests in fixed time buckets
{ algorithm: 'fixed-window', limit: 100, window: '1m' }

// Sliding window - smooths out bursts at window boundaries
{ algorithm: 'sliding-window', limit: 100, window: '1m' }

// Token bucket - allows bursts, then enforces a steady rate
{ algorithm: 'token-bucket', limit: 100, refill: { amount: 10, interval: '6s' } }

Config

| Option | Type | Default | Description | |---|---|---|---| | redis | ioredis or node-redis | | Redis client, auto-detected | | algorithm | 'fixed-window' 'sliding-window' 'token-bucket' | | Algorithm to use | | limit | number | | Max requests per window, or bucket capacity | | window | string | | Time window: '30s', '5m', '1h', '1d' | | refill | { amount, interval } | | Refill config: how many tokens to add and how often (token bucket only) | | prefix | string | 'rl' | Redis key prefix | | fail | 'open' or 'closed' | 'closed' | What happens when Redis is down | | ban | object | | Ban escalation (see below) |

Methods

await limiter.limit('key')              // check + consume 1 token
await limiter.limit('key', { cost: 5 }) // consume multiple tokens
await limiter.peek('key')               // check without consuming
await limiter.reset('key')              // clear all state for a key
await limiter.block('key', '1h')        // manually block a key

Every limit() and peek() call returns:

{
  success: boolean           // allowed or denied
  remaining: number          // how many requests are left
  reset: number              // when the limit resets (unix ms)
  limit: number              // the configured max
  headers: {                 // ready to set on your HTTP response
    'RateLimit-Limit': string
    'RateLimit-Remaining': string
    'RateLimit-Reset': string
    'Retry-After'?: string   // only included when denied
  }
}

Ban Escalation

Automatically block repeat offenders with increasing ban durations:

const limiter = new Limiter({
  redis,
  algorithm: 'sliding-window',
  limit: 100,
  window: '1m',
  ban: {
    escalation: ['3m', '15m', '1h'],  // 1st offense: 3m, 2nd: 15m, 3rd+: 1h
    history: '24h',                     // escalation resets after 24h
  },
})

Bans trigger automatically when a request is denied. While banned, all requests are rejected without further escalation. peek() never triggers bans. reset() clears ban history, including shared ban state.

To share bans across limiters (e.g., API ban also blocks OAuth):

ban: {
  escalation: ['3m', '15m', '1h'],
  history: '24h',
  shared: 'rl',  // all limiters with the same shared prefix share ban state
}

Examples

Login Protection

const loginLimit = new Limiter({
  redis,
  algorithm: 'sliding-window',
  limit: 5,
  window: '15m',
  prefix: 'login',
  ban: {
    escalation: ['15m', '1h', '24h'],
    history: '7d',
  },
})

const { success } = await loginLimit.limit(ip)
if (!success) return res.status(429).json({ error: 'Too many login attempts' })

API Key

const apiLimit = new Limiter({
  redis,
  algorithm: 'token-bucket',
  limit: 100,
  refill: { amount: 10, interval: '6s' },
  prefix: 'api',
})

const { success, headers } = await apiLimit.limit(apiKey)

See the examples folder for usage with Express, Next.js, Fastify, and Hono.

Requirements

  • Node.js 20+
  • Redis 5.0+