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>
): RateLimiterOptions
keystring | (context: T) => stringA unique identifier for the rate limit. Can be a static string or a function that receives context and returns a unique key.
maxnumberMaximum number of requests allowed within the time window.
windowstring | numberTime 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
allowedbooleanWhether the request should be allowed (true) or rate limited (false).
remainingnumberNumber of requests remaining in the current window. Returns 0 if rate limited.
retryAfternumberMilliseconds 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>
): RequestHandlerExample
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
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
allowedbooleanWhether the action is currently allowed.
remainingnumberNumber of actions remaining in the current window.
retryAfternumberMilliseconds 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}