Express
Keep Express behavior outside the core limiter. The middleware translates a
rate-limit decision into HTTP headers and a 429 response.
import type { RequestHandler } from 'express';
export const rateLimit: RequestHandler = async (request, response, next) => { try { const identifier = request.ip ?? 'unknown'; const result = await limiter.consume(identifier);
response.setHeader('RateLimit-Remaining', String(result.remaining)); response.setHeader('RateLimit-Reset', String(result.resetAt));
if (!result.allowed) { response.setHeader('Retry-After', String(Math.ceil(result.retryAfterMs / 1000))); response.status(429).json({ message: 'Too many requests' }); return; }
next(); } catch (error) { // Configuration and store errors from limix carry a stable `code` via // RateLimiterConfigurationError / RateLimiterStoreError, so an Express // error handler can distinguish them from unrelated application errors. next(error); }};Prefer authenticated user, tenant, or API-key identifiers where possible. IP addresses can represent many users behind a proxy and require careful trusted proxy configuration.