Rate Limiting: La Primera Línea de Defensa de Tu API
Sin rate limiting, un solo usuario (o bot) puede sobrecargar tu API con miles de requests por segundo. Rate limiting limita el número de solicitudes que un cliente puede hacer en una ventana de tiempo.
Algoritmos Comunes
| Algoritmo | Cómo Funciona | Pros | Contras |
|---|---|---|---|
| Fixed Window | Cuenta requests por ventana fija de tiempo | Simple | Burst en los bordes de la ventana |
| Sliding Window | Cuenta requests en ventana deslizante | Distribución suave | Más memoria |
| Token Bucket | Tokens se reabastecen a tasa fija; cada request cuesta un token | Permite bursts controlados | Ligeramente complejo |
Headers de Respuesta
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1682345700
HTTP/1.1 429 Too Many Requests
Retry-After: 30
{ "error": "Rate limit excedido" }Express.js con Redis
import rateLimit from 'express-rate-limit';
import RedisStore from 'rate-limit-redis';
const limiter = rateLimit({
windowMs: 60 * 1000,
max: 100,
standardHeaders: true,
store: new RedisStore({
sendCommand: (...args) => redis.call(...args),
}),
});
app.use('/api/', limiter);
const strictLimiter = rateLimit({ windowMs: 60000, max: 10 });
app.post('/api/auth/login', strictLimiter, loginHandler);Sliding Window DIY con Redis
async function checkRateLimit(userId, limit = 100, window = 60) {
const key = `rate:${userId}`;
const now = Date.now();
const windowStart = now - window * 1000;
const pipeline = redis.pipeline();
pipeline.zremrangebyscore(key, 0, windowStart);
pipeline.zadd(key, now, `${now}:${Math.random()}`);
pipeline.zcard(key);
pipeline.expire(key, window);
const results = await pipeline.exec();
const count = results[2][1];
return { allowed: count <= limit, remaining: Math.max(0, limit - count) };
}Buenas Prácticas
- Retorna status
429con headerRetry-After - Incluye headers de rate limit en toda respuesta
- Usa límites diferentes por endpoint
- Registra rate limit hits para detección de abuso