Express Daq Rate Limiter Middleware mach
unprotected API endpoint invitation: wa' misbehaving client script, wa' retry loop backoff pagh, wa' scraper - server poH Hoch same handful clients serve (others pagh). Rate limiting 'oH Qotlh: window Daq client request mI' Dach. 40 lines Daq solid limiter mach laH, dependency pagh.
rate limiting nuq
rate limiter client per requests track (IP address pagh API key), threshold window Daq cross vaj reject: "100 requests per minute". window Qaw'DI' count reset, client requests chu'.
simplest correct implementation fixed window counter: client Hoch count 'ej window-start timestamp. request Hoch increment; window expire vaj reset.
minimal fixed-window limiter
function createRateLimiter({ windowMs, max }) {
const clients = new Map();
return function rateLimiter(req, res, next) {
const key = req.ip;
const now = Date.now();
const entry = clients.get(key);
if (!entry || now - entry.windowStart >= windowMs) {
clients.set(key, { windowStart: now, count: 1 });
return next();
}
if (entry.count >= max) {
const retryAfterMs = windowMs - (now - entry.windowStart);
res.setHeader('Retry-After', Math.ceil(retryAfterMs / 1000));
return res.status(429).json({ error: 'Too many requests' });
}
entry.count += 1;
next();
};
}
Express app Daq wire:
const express = require('express');
const app = express();
const limiter = createRateLimiter({ windowMs: 60_000, max: 100 });
app.use('/api/', limiter);
app.get('/api/posts', (req, res) => {
res.json({ posts: [] });
});
app.listen(3000);
client Hoch 100 requests 60-second window Daq, 429 Too Many Requests legh, Retry-After header (qaSDI' return).
fixed-window Qagh: boundary bursts
fixed windows Qagh: client max requests window last second Daq, next window first second Daq max chel - 2x rate, two-second burst boundary Daq.
window 1: [ ......................############] <- 100 requests, last second
window 2: [############......................] <- 100 more, first second
API law' vaD Qatlh pagh. Qatlh vaj sliding window log: client per counter pagh, request Hoch timestamp store, now - windowMs Daq count.
function createSlidingWindowLimiter({ windowMs, max }) {
const clients = new Map();
return function rateLimiter(req, res, next) {
const key = req.ip;
const now = Date.now();
const timestamps = clients.get(key) ?? [];
const windowStart = now - windowMs;
const recent = timestamps.filter((t) => t > windowStart);
if (recent.length >= max) {
clients.set(key, recent);
res.setHeader('Retry-After', Math.ceil((recent[0] - windowStart) / 1000));
return res.status(429).json({ error: 'Too many requests' });
}
recent.push(now);
clients.set(key, recent);
next();
};
}
exact 'ach memory law' (request client per timestamp). high-traffic API vaD hybrid sliding window counter: previous window count weight (current overlap). code pagh math law'. teams library pagh proxy-level limiter (nginx limit_req, Redis-backed) lo'.
rate-limiting key choose
req.ip obvious key 'ach shared NAT (office engineers wa' public IP) pagh real client address forward pagh proxy Daq Qaw'. cha' adjustments:
- proxy trust correct. nginx pagh load balancer Daq
req.ipproxy address (Express trust configure pagh vaj):app.set('trust proxy', 1),req.ipX-Forwarded-Forvo'. Qagh vaj client Hoch wa' rap limited. - API key IP law' prefer. authenticated endpoints API key pagh user ID per limit (IP pagh) - actual identity, IP change 'ej shared networks survive.
stale entries clean
Map cha' implementations Daq forever grow (old entries evict pagh vaj) - slow memory leak. periodic sweep:
setInterval(() => {
const cutoff = Date.now() - windowMs;
for (const [key, entry] of clients) {
if (entry.windowStart < cutoff) clients.delete(key);
}
}, windowMs).unref();
.unref() Node Daq qatlh: event loop process alive timer neH vaD pagh, graceful shutdown interfere pagh.
library lo'
express-rate-limit Hoch implement (IPv6, pluggable stores) single-process app vaD default Dun. load balancer Daq multiple instances vaj in-memory Map Qu'be': instance Hoch own counters, client max per instance (total pagh). shared store poQ; express-rate-limit Redis-backed store support.
yaj
rate limiter counter time window rap - Hoch refinement. fixed window wa'DIch: simple, cheap, API law' vaD correct. boundary bursts measured problem vaj sliding window. server process wa' law' vaj shared store.