Que es el Rate Limiting
El rate limiting (limitacion de tasa) es un mecanismo que limita el numero de solicitudes API en un periodo de tiempo determinado. Mantiene la estabilidad del servicio y protege el sistema contra uso malicioso o acceso excesivo debido a errores.
Por que es necesario: Si se aceptan solicitudes sin limite, un solo usuario podria agotar todos los recursos del sistema, o el servicio podria caerse por un ataque DDoS.
Objetivos del Rate Limiting
| Objetivo | Descripcion |
|---|---|
| Proteccion del servicio | Prevenir caidas por sobrecarga |
| Garantizar equidad | Distribuir recursos equitativamente entre todos los usuarios |
| Prevencion de abuso | Disuadir scraping, ataques de fuerza bruta |
| Gestion de costos | Asegurar predictibilidad en costos de infraestructura |
Algoritmos Principales
1. Ventana Fija (Fixed Window)
Reinicia el contador en cada ventana de tiempo fijo.
Configuracion: Ventana de 1 minuto (00:00-00:59), limite de 100 solicitudes/minuto
| Tiempo | Solicitudes | Resultado |
|---|---|---|
| 00:00-00:30 | 90 | ✓ |
| 00:30-00:59 | 10 | ✓ (total 100) |
| 01:00 | Reinicio del contador | |
| 01:00-01:30 | 100 | ✓ |
Problema: En el limite de la ventana, es posible el doble de solicitudes instantaneamente
| Tiempo | Solicitudes | Problema |
|---|---|---|
| 00:59 | 100 | ✓ |
| 01:00 | 100 | ✓ |
| → 200 solicitudes en 2 segundos! |
2. Ventana Deslizante con Log (Sliding Window Log)
Registra el timestamp de cada solicitud y cuenta las solicitudes en los ultimos N segundos.
Hora actual: 01:00:30, Ventana: Ultimos 60 segundos (00:00:30-01:00:30)
| Timestamp | Estado |
|---|---|
| 00:00:25 | Fuera de ventana (eliminar) |
| 00:00:35 | ✓ Valido |
| 00:00:50 | ✓ Valido |
| 01:00:10 | ✓ Valido |
Ventaja: Rate limiting preciso Desventaja: Alto uso de memoria
3. Ventana Deslizante con Contador (Sliding Window Counter)
Version mejorada de la ventana fija. Calcula ponderando los contadores de las ventanas anterior y actual.
| Ventana | Numero de solicitudes |
|---|---|
| Anterior (00:00-00:59) | 80 |
| Actual (01:00-01:59) | 30 |
| Hora actual | 01:00:20 (33% transcurrido) |
Calculo: Solicitudes estimadas = 80 x 0.67 + 30 = 83.6
4. Token Bucket
Los tokens se agregan al bucket a una tasa constante, y cada solicitud consume un token.
Configuracion: Capacidad del bucket 10 tokens, tasa de recarga 1 token/segundo
| Estado | Tokens | Nota |
|---|---|---|
| Estado inicial | 10/10 | Lleno |
| Despues de 5 solicitudes | 5/10 | 5 tokens consumidos |
| 3 segundos despues | 8/10 | 3 tokens recargados |
Burst: 8 solicitudes disponibles actualmente
Ventaja: Soporta bursts, eficiente en memoria
5. Leaky Bucket
Las solicitudes se procesan desde el bucket a una tasa constante.
flowchart LR
In["Entrada<br/>(variable)"] --> Bucket["Bucket<br/>(cola)"] --> Out["Salida<br/>(tasa fija)"]
Ventaja: Tasa de salida estable Desventaja: Dificil de manejar bursts
Patrones de Implementacion
Headers de Respuesta
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1640000000
Respuesta cuando se Excede el Limite
HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/json
{
"error": "rate_limit_exceeded",
"message": "Se ha excedido el limite de tasa. Por favor, reintente en 30 segundos.",
"retry_after": 30
}
Ejemplo de Implementacion con Redis
async function checkRateLimit(userId, limit, windowSec) {
const key = `ratelimit:${userId}`;
const current = await redis.incr(key);
if (current === 1) {
await redis.expire(key, windowSec);
}
if (current > limit) {
const ttl = await redis.ttl(key);
return { allowed: false, retryAfter: ttl };
}
return { allowed: true, remaining: limit - current };
}
Granularidad del Limite
Basado en Usuario
| Usuario | Limite |
|---|---|
| Usuario A | 100 solicitudes/minuto |
| Usuario B | 100 solicitudes/minuto |
Basado en Direccion IP
| Direccion IP | Limite |
|---|---|
| 192.168.1.1 | 100 solicitudes/minuto |
| 192.168.1.2 | 100 solicitudes/minuto |
Basado en Endpoint
| Endpoint | Limite | Nota |
|---|---|---|
| GET /api/users | 100 solicitudes/minuto | |
| POST /api/users | 10 solicitudes/minuto | Mas estricto para creacion |
Jerarquico
| Plan | Limite |
|---|---|
| Free tier | 100 solicitudes/dia |
| Pro tier | 10,000 solicitudes/dia |
| Enterprise | Ilimitado |
Consideraciones en Sistemas Distribuidos
Centralizado
flowchart LR
S1["Servidor 1"] --> Redis["Redis<br/>(contador compartido)"]
S2["Servidor 2"] --> Redis
S3["Servidor 3"] --> Redis
Ventaja: Preciso Desventaja: Latencia hacia Redis
Cache Local + Sincronizacion
flowchart LR
S1["Servidor 1<br/>Contador local"] <-->|Sincronizacion periodica| S2["Servidor 2<br/>Contador local"]
Ventaja: Baja latencia Desventaja: Permite ligero exceso
Manejo del Lado del Cliente
Backoff Exponencial
async function fetchWithRetry(url, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || Math.pow(2, i);
await sleep(retryAfter * 1000);
continue;
}
return response;
}
throw new Error('Rate limit exceeded after retries');
}
Resumen
El rate limiting es un mecanismo importante para asegurar la estabilidad y equidad de las APIs. Al seleccionar el algoritmo apropiado para el caso de uso, como token bucket o sliding window, y configurar limites con la granularidad adecuada, se puede proteger el servicio mientras se proporciona una buena experiencia de usuario.
← Volver a la lista