Skip to content

API Reference

rateLimit(options?)

Creates a rate limiter function.

ts
import { rateLimit } from 'universal-rate-limit';

const limiter = rateLimit(options);
const result: RateLimitResult = await limiter(request);

Parameters:

OptionTypeDefaultDescription
windowMsnumber60_000Time window in milliseconds
limitnumber | (req: Request) => number | Promise<number>60Maximum requests per window
algorithm'fixed-window' | 'sliding-window''fixed-window'Rate limiting algorithm
headers'draft-7' | 'draft-6''draft-7'IETF headers version
storeStorenew MemoryStore(...)Storage backend
keyGenerator(req: Request) => string | Promise<string>IP-basedExtract client identifier
skip(req: Request) => boolean | Promise<boolean>undefinedSkip rate limiting
handler(req: Request, result: RateLimitResult) => Response | Promise<Response>undefinedCustom response handler
messagestring | Record<string, unknown> | (req, result) => string | Record<string, unknown>'Too Many Requests'Response body
statusCodenumber429HTTP status code
passOnStoreErrorbooleanfalseFail open on store errors

Returns: (request: Request) => Promise<RateLimitResult>


RateLimitResult

The result object returned by the limiter function.

ts
interface RateLimitResult {
    limited: boolean;
    limit: number;
    remaining: number;
    resetTime: Date;
    headers: Record<string, string>;
}
FieldTypeDescription
limitedbooleanWhether the request is rate limited
limitnumberMaximum requests allowed in the window
remainingnumberRequests remaining in the current window
resetTimeDateWhen the current window resets
headersRecord<string, string>IETF rate limit headers to set on the response. Includes Retry-After when limited is true.

buildRateLimitResponse(request, result, options)

Helper used by middleware adapters to build a 429 response.

ts
import { buildRateLimitResponse } from 'universal-rate-limit';

const response = await buildRateLimitResponse(request, result, {
    handler: undefined,
    message: 'Too Many Requests',
    statusCode: 429
});

Parameters:

ParameterTypeDescription
requestRequestThe original request
resultRateLimitResultThe rate limit result
options.handler(req, result) => ResponseCustom response handler (takes priority)
options.messagestring | object | functionResponse body
options.statusCodenumberHTTP status code

Returns: Promise<Response>


MemoryStore

In-memory store implementation with dual-map design for efficient sliding-window support.

ts
import { MemoryStore } from 'universal-rate-limit';

const store = new MemoryStore(windowMs, algorithm);

Constructor:

ParameterTypeDescription
windowMsnumberWindow duration in milliseconds
algorithm'fixed-window' | 'sliding-window'Algorithm to use

Methods:

MethodDescription
increment(key)Increment counter, returns Promise<IncrementResult>
decrement(key)Decrement counter
resetKey(key)Reset a single key
resetAll()Clear all entries
shutdown()Stop the cleanup timer

RedisStore

Redis-backed store from @universal-rate-limit/redis. Uses Lua scripts for atomic operations.

ts
import { RedisStore } from '@universal-rate-limit/redis';

const store = new RedisStore({
    sendCommand: (...args) => redis.call(...args),
    windowMs: 60_000,
    prefix: 'rl:',
    resetExpiryOnChange: false
});

Constructor:

ParameterTypeDefaultDescription
sendCommandSendCommandFnRequired. Sends a raw Redis command.
windowMsnumberRequired. Window duration in ms.
prefixstring'rl:'Key prefix for all rate limit keys.
resetExpiryOnChangebooleanfalseReset the TTL on every increment.

Methods:

MethodDescription
increment(key)Increment counter, returns Promise<IncrementResult>
decrement(key)Decrement counter
resetKey(key)Reset a single key
resetAll()Clear all prefixed keys via SCAN + DEL

Store Interface

Implement this interface for custom storage backends.

ts
interface Store {
    increment(key: string): Promise<IncrementResult>;
    decrement(key: string): Promise<void>;
    resetKey(key: string): Promise<void>;
    resetAll(): Promise<void>;
}

interface IncrementResult {
    totalHits: number;
    resetTime: Date;
}

Types

ts
type Algorithm = 'fixed-window' | 'sliding-window';
type HeadersVersion = 'draft-6' | 'draft-7';

Store Exports

@universal-rate-limit/redis

ts
import { RedisStore } from '@universal-rate-limit/redis';

RedisStore — Client-agnostic Redis store. Also re-exports Store and IncrementResult from core.


Middleware Exports

@universal-rate-limit/express

ts
import { expressRateLimit } from '@universal-rate-limit/express';

expressRateLimit(options?) — Returns an Express RequestHandler.

@universal-rate-limit/fastify

ts
import { fastifyRateLimit } from '@universal-rate-limit/fastify';

fastifyRateLimit — Fastify plugin. Register with fastify.register(fastifyRateLimit, options).

@universal-rate-limit/hono

ts
import { honoRateLimit } from '@universal-rate-limit/hono';

honoRateLimit(options?) — Returns a Hono MiddlewareHandler.

@universal-rate-limit/nextjs

ts
import { withRateLimit, nextjsRateLimit } from '@universal-rate-limit/nextjs';
  • withRateLimit(handler, options?) — Wraps a Next.js App Router handler with rate limiting.
  • nextjsRateLimit(options?) — Creates a limiter for Edge Middleware use.

All middleware packages also re-export: RateLimitOptions, RateLimitResult, Store, IncrementResult, MemoryStore.

Released under the MIT License.