API Reference

Complete documentation for all exports and methods

createRateLimiter

Creates a new rate limiter instance with the specified configuration.

Signature

function createRateLimiter<T = any>(
  options: RateLimiterOptions<T>
): RateLimiter

Options

keystring | (context: T) => string

A unique identifier for the rate limit. Can be a static string or a function that receives context and returns a unique key.

maxnumber

Maximum number of requests allowed within the time window.

windowstring | number

Time window for the rate limit. Accepts human-readable strings ("10s", "1m", "1h", "1d") or milliseconds.

storageStorageAdapter (optional)

Storage adapter for persisting rate limit data. Defaults to MemoryStorage if not specified.

Example

1import { createRateLimiter, MemoryStorage } from 'universal-rate-limiter';
2
3const limiter = createRateLimiter({
4  key: 'api-requests',
5  max: 100,
6  window: '15m',
7  storage: new MemoryStorage()
8});

limiter.check()

Checks if a request should be allowed based on the rate limit configuration.

Signature

async function check(context?: T): Promise<RateLimitResult>

Returns

allowedboolean

Whether the request should be allowed (true) or rate limited (false).

remainingnumber

Number of requests remaining in the current window. Returns 0 if rate limited.

retryAfternumber

Milliseconds until the rate limit resets. Returns 0 if allowed.

Example

1const result = await limiter.check();
2
3if (result.allowed) {
4  console.log(`Allowed. ${result.remaining} requests remaining.`);
5  // Process request
6} else {
7  console.log(`Rate limited. Retry after ${result.retryAfter}ms`);
8  // Return 429 status
9}

rateLimitExpress

Express middleware for rate limiting. Automatically handles rate limit checks and responses.

Signature

function rateLimitExpress(
  options: RateLimiterOptions<Request>
): RequestHandler

Example

1import express from 'express';
2import { rateLimitExpress } from 'universal-rate-limiter';
3
4const app = express();
5
6// Global rate limit
7app.use(rateLimitExpress({
8  key: 'global',
9  max: 100,
10  window: '15m'
11}));
12
13// Per-IP rate limit
14app.use(rateLimitExpress({
15  key: (req) => `ip-${req.ip}`,
16  max: 50,
17  window: '5m'
18}));
19
20// Route-specific rate limit
21app.post('/api/auth/login',
22  rateLimitExpress({
23    key: (req) => `login-${req.ip}`,
24    max: 5,
25    window: '15m'
26  }),
27  (req, res) => {
28    // Handle login
29  }
30);

rateLimitEdge

Edge middleware for Next.js 16+ (use in proxy.ts). Optimized for edge runtime.

Signature

function rateLimitEdge(options: {
  key: string | ((request: Request) => string);
  max: number;
  window: string | number;
  storage?: StorageAdapter;
  onRateLimit?: (request: Request) => Response;
}): (request: Request) => Promise<Response>

Example

proxy.ts
1import { rateLimitEdge } from 'universal-rate-limiter';
2
3export default rateLimitEdge({
4  key: (request) => request.headers.get('x-forwarded-for') ?? 'anonymous',
5  max: 100,
6  window: '1m',
7  onRateLimit: (request) => {
8    return new Response(
9      JSON.stringify({ error: 'Too many requests' }),
10      {
11        status: 429,
12        headers: {
13          'Content-Type': 'application/json',
14          'Retry-After': '60'
15        }
16      }
17    );
18  }
19});
20
21export const config = {
22  matcher: '/api/:path*',
23};

useRateLimit

React hook for client-side rate limiting. Uses localStorage for persistence.

Signature

function useRateLimit(
  key: string,
  options: { max: number; window: string | number }
): {
  allowed: boolean;
  remaining: number;
  retryAfter: number;
  attempt: () => Promise<void>;
}

Returns

allowedboolean

Whether the action is currently allowed.

remainingnumber

Number of actions remaining in the current window.

retryAfternumber

Milliseconds until the limit resets.

attempt() => Promise<void>

Function to call when performing the rate-limited action.

Example

1'use client';
2
3import { useRateLimit } from 'universal-rate-limiter';
4
5export function LikeButton() {
6  const { allowed, remaining, attempt } = useRateLimit('like-button', {
7    max: 10,
8    window: '1m'
9  });
10
11  const handleLike = async () => {
12    if (!allowed) {
13      alert('Too many likes! Please wait.');
14      return;
15    }
16
17    await attempt();
18    // Send like to API
19    console.log(`Liked! ${remaining} likes remaining.`);
20  };
21
22  return (
23    <button onClick={handleLike} disabled={!allowed}>
24      ❤️ Like ({remaining})
25    </button>
26  );
27}

Storage Adapters

MemoryStorage

In-memory storage adapter. Fast but data is lost on server restart. Good for development and single- instance deployments.

import { MemoryStorage } from 'universal-rate-limiter';

const storage = new MemoryStorage();

LocalStorageAdapter

Browser localStorage adapter. Persists data across page reloads. Only available in browser environments.

import { LocalStorageAdapter } from 'universal-rate-limiter';

const storage = new LocalStorageAdapter();

Custom Storage Adapter

You can create custom storage adapters by implementing the StorageAdapter interface:

1interface StorageAdapter {
2  get(key: string): Promise<number | null>;
3  set(key: string, value: number, ttl: number): Promise<void>;
4  delete(key: string): Promise<void>;
5}
6
7// Example: Redis adapter
8class RedisStorageAdapter implements StorageAdapter {
9  constructor(private redis: RedisClient) {}
10
11  async get(key: string): Promise<number | null> {
12    const value = await this.redis.get(key);
13    return value ? parseInt(value, 10) : null;
14  }
15
16  async set(key: string, value: number, ttl: number): Promise<void> {
17    await this.redis.set(key, value.toString(), 'PX', ttl);
18  }
19
20  async delete(key: string): Promise<void> {
21    await this.redis.del(key);
22  }
23}