Funcionamiento del Rate Limiting - Control de Acceso para Proteger APIs

14 min de lectura | 2025.12.13

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

ObjetivoDescripcion
Proteccion del servicioPrevenir caidas por sobrecarga
Garantizar equidadDistribuir recursos equitativamente entre todos los usuarios
Prevencion de abusoDisuadir scraping, ataques de fuerza bruta
Gestion de costosAsegurar 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

TiempoSolicitudesResultado
00:00-00:3090
00:30-00:5910✓ (total 100)
01:00Reinicio del contador
01:00-01:30100

Problema: En el limite de la ventana, es posible el doble de solicitudes instantaneamente

TiempoSolicitudesProblema
00:59100
01:00100
→ 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)

TimestampEstado
00:00:25Fuera 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.

VentanaNumero de solicitudes
Anterior (00:00-00:59)80
Actual (01:00-01:59)30
Hora actual01: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

EstadoTokensNota
Estado inicial10/10Lleno
Despues de 5 solicitudes5/105 tokens consumidos
3 segundos despues8/103 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

UsuarioLimite
Usuario A100 solicitudes/minuto
Usuario B100 solicitudes/minuto

Basado en Direccion IP

Direccion IPLimite
192.168.1.1100 solicitudes/minuto
192.168.1.2100 solicitudes/minuto

Basado en Endpoint

EndpointLimiteNota
GET /api/users100 solicitudes/minuto
POST /api/users10 solicitudes/minutoMas estricto para creacion

Jerarquico

PlanLimite
Free tier100 solicitudes/dia
Pro tier10,000 solicitudes/dia
EnterpriseIlimitado

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