Skip to content
IRC-CodingIRC-Coding
Rate LimitingRedisImplementaciónDistributed SystemsAPI GatewayToken Bucket

API Rate Limiting: Implementación para sistemas distribuidos

Implementa Rate Limiting en APIs: algoritmos, Redis, headers, código y mejores prácticas para sistemas distribuidos.

S

schutzgeist

7 min read
API Rate Limiting: Implementación para sistemas distribuidos

Implementación de Rate Limiting en APIs

El rate limiting en sistemas distribuidos requiere gestión consistente del estado, la elección correcta del algoritmo y comunicación clara con los clientes.

Descripción concisa

La implementación de rate limiting en APIs consiste en establecer límites técnicos sobre las solicitudes que llegan a un servicio. En sistemas distribuidos, el límite debe aplicarse consistentemente en todas las instancias, lo que requiere un almacenamiento centralizado como Redis o una base de datos. Los algoritmos principales son Fixed Window, Sliding Window, Token Bucket y Leaky Bucket. Cada uno tiene propiedades distintas en cuanto a equidad, comportamiento ante picos de tráfico y complejidad de implementación. Al implementar, hay que considerar detalles críticos como la identificación del cliente, operaciones atómicas, headers de estado, manejo de errores con 429 y Retry-After, así como la selección de límites apropiados. El rate limiting no debería estar solo en el código de la aplicación, sino también ser configurable en el API Gateway o Load Balancer para ofrecer protección en múltiples capas.

Componentes clave

Identificación del cliente

El rate limiting necesita identificar de forma única a cada cliente. Esto se puede hacer mediante API Keys, IDs de usuario, direcciones IP o combinaciones de varios factores. Para clientes autenticados, la ID de usuario suele ser la mejor opción, ya que las direcciones IP cambian y múltiples clientes pueden compartir una misma IP.

Implementación de Fixed Window

Fixed Window cuenta solicitudes en ventanas de tiempo fijas. En Redis se almacena un contador por ventana y cliente. El contador se crea en la primera solicitud de la ventana y expira después del tiempo establecido. Si el contador supera el límite, se rechaza la solicitud.

Implementación de Sliding Window

Sliding Window es más justo que Fixed Window, pero más complejo. Una variante es Sliding Window Log, donde se mantiene una lista de timestamps de todas las solicitudes recientes de cada cliente. Se eliminan las solicitudes que caen fuera de la ventana. Si la cantidad de solicitudes restantes supera el límite, se rechaza la nueva solicitud.

Implementación de Token Bucket

Token Bucket es un algoritmo muy usado. Un bucket tiene una capacidad máxima y se llena con tokens a una tasa constante. Cada solicitud consume un token. Si el bucket está vacío, se rechaza la solicitud o se retrasa. Redis es ideal para Token Bucket usando scripts Lua para operaciones atómicas.

Implementación de Leaky Bucket

Leaky Bucket procesa solicitudes a una tasa constante. Las solicitudes se ponen en cola y se procesan de forma uniforme. El algoritmo es excelente para procesamiento consistente, pero puede causar tiempos de espera y rechazo cuando la cola está llena.

Redis para rate limiting distribuido

Redis ofrece operaciones atómicas rápidas y TTL, lo que lo hace ideal para rate limiting. Los scripts Lua permiten ejecutar múltiples comandos de forma atómica. Redis Cluster o Redis Sentinel proporcionan alta disponibilidad. En casos de muy alta demanda, Redis puede convertirse en un cuello de botella, por lo que se pueden complementar con caché local o proxys con caché local.

Operaciones atómicas

El rate limiting debe ser atómico para evitar race conditions. Si múltiples solicitudes verifican simultáneamente si queda límite disponible, el límite no debe ser superado. Los scripts Lua en Redis o transacciones en bases de datos garantizan la atomicidad.

Headers para indicar estado

Los clientes deben saber cuál es su estado actual. Headers como X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset son ampliamente usados. Alternativamente, se puede usar el esquema RFC-RateLimit. Estos headers permiten que los clientes ajusten su tasa de solicitudes.

Manejo de errores con 429

Cuando se supera el límite, la API responde con 429 Too Many Requests. El header Retry-After debe indicar cuándo el cliente puede reintentar. La respuesta de error debe seguir RFC 7807 Problem Details y no contener detalles internos.

Límites por endpoint y por usuario

Diferentes endpoints tienen costos distintos. Las operaciones de escritura y consultas costosas deben tener límites más estrictos que operaciones simples de lectura. De igual forma, distintos grupos de usuarios pueden recibir límites diferentes, por ejemplo clientes gratuitos y de pago.

Rate limiting en API Gateway

Los API Gateways como Kong, Nginx o AWS API Gateway incluyen rate limiting integrado. Protegen la API antes de que las solicitudes lleguen al backend. Los gateways son particularmente efectivos para límites globales y reglas simples, mientras que el código de la aplicación puede manejar reglas más complejas y específicas de usuario.

Ejemplo práctico

Un servicio Node.js implementa Token Bucket rate limiting con Redis.

const redis = require('redis');
const client = redis.createClient();

const LIMIT = 100;
const WINDOW_SECONDS = 60;

async function isAllowed(clientId) {
  const key = `rate_limit:${clientId}`;
  const lua = `
    local key = KEYS[1]
    local limit = tonumber(ARGV[1])
    local window = tonumber(ARGV[2])
    local current = redis.call('GET', key)
    if current == false then
      current = 0
    end
    current = tonumber(current)
    if current >= limit then
      return 0
    end
    redis.call('INCR', key)
    if current == 0 then
      redis.call('EXPIRE', key, window)
    end
    return 1
  `;

  const result = await client.eval(lua, { keys: [key], arguments: [String(LIMIT), String(WINDOW_SECONDS)] });
  return result === 1;
}

Middleware en Express:

async function rateLimit(req, res, next) {
  const clientId = req.user?.id || req.ip;
  const allowed = await isAllowed(clientId);
  if (!allowed) {
    res.set('Retry-After', String(WINDOW_SECONDS));
    return res.status(429).json({
      type: 'https://api.example.com/problems/rate-limit-exceeded',
      title: 'Rate limit excedido',
      status: 429,
      detail: `Has excedido el límite de ${LIMIT} solicitudes por ${WINDOW_SECONDS} segundos.`
    });
  }
  next();
}

Este enfoque es atómico, funciona en múltiples instancias de servidor y comunica claramente los límites al cliente.

FAQ: Implementación de Rate Limiting en APIs

1. ¿Cómo se identifica a un cliente para rate limiting?

Los clientes se identifican principalmente mediante API Keys, IDs de usuario o direcciones IP. Para APIs autenticadas, la ID de usuario suele ser la opción más confiable.

2. ¿Por qué Redis es adecuado para rate limiting?

Redis es rápido, ofrece operaciones atómicas y TTL, y es accesible centralmente en sistemas distribuidos. Los scripts Lua permiten operaciones de conteo atómicas complejas.

3. ¿Qué es Token Bucket en la implementación?

Un Token Bucket se llena con tokens a una tasa constante. Cada solicitud consume un token. Si el bucket está vacío, se rechaza la solicitud. Redis y scripts Lua permiten una implementación atómica.

4. ¿Qué es rate limiting atómico?

El rate limiting atómico asegura que la verificación y actualización del límite ocurran como una operación indivisible. Esto evita race conditions y superaciones del límite en solicitudes paralelas.

5. ¿Qué es Sliding Window Log?

Sliding Window Log almacena el timestamp de cada solicitud de un cliente. Se eliminan las solicitudes fuera de la ventana. Si la cantidad de solicitudes restantes supera el límite, se rechaza la nueva solicitud.

6. ¿Qué es Fixed Window?

Fixed Window cuenta solicitudes en ventanas de tiempo fijas. Es simple de implementar, pero puede causar picos al final e inicio de cada ventana.

7. ¿Qué es Leaky Bucket?

Leaky Bucket pone las solicitudes en cola y las procesa a una tasa constante. Suaviza mucho el tráfico, pero puede causar tiempos de espera.

8. ¿Qué es una race condition en rate limiting?

Ocurre cuando múltiples solicitudes paralelas verifican y actualizan el límite simultáneamente. Sin operaciones atómicas, el límite puede ser superado.

9. ¿Qué headers se deben establecer en rate limiting?

Headers como X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset y Retry-After informan a los clientes sobre su límite y el próximo momento permitido.

10. ¿Qué es 429 Too Many Requests?

429 Too Many Requests es el código de estado HTTP que indica que un cliente ha superado el rate limit. Junto con Retry-After, permite reintentos justos.

11. ¿Debería ocurrir rate limiting en el Gateway o en el código?

Ambos son útiles. Los gateways son adecuados para límites globales y simples, mientras que el código de aplicación maneja reglas más complejas y específicas de usuario o endpoint.

12. ¿Qué son límites por endpoint?

Los límites por endpoint se aplican a endpoints individuales. Las operaciones de escritura y consultas costosas reciben límites más estrictos que operaciones simples de lectura.

13. ¿Qué es un cuello de botella en rate limiting?

Ocurre cuando el almacenamiento central de rate limiting, como Redis, se sobrecarga. Las soluciones incluyen caché, proxys con caché local o estructuras de datos optimizadas.

14. ¿Qué es una buena estrategia de rate limiting?

Una buena estrategia combina identificación del cliente, el algoritmo correcto, operaciones atómicas, headers informativos, límites sensatos por endpoint y usuario, manejo claro de errores y monitoreo.

15. ¿Cuál es la ventaja de Retry-After?

Retry-After le dice al cliente cuándo puede reenviar la solicitud. Esto reduce solicitudes innecesarias, cuida la API y mejora la tasa de éxito en reintentos.

Continuamos en el itinerario de aprendizaje de APIs

El siguiente artículo en el itinerario de aprendizaje de APIs aborda Rate Limiting y Throttling para APIs — estrategias y algoritmos para Rate Limiting, así como diferencias entre Rate Limiting y Throttling.

Fuentes

  1. https://www.rfc-editor.org/rfc/rfc6585
  2. https://redis.io/docs/manual/programmability/eval-intro/
  3. https://www.konghq.com/kong

Recomendaciones de libros para el desarrollo de APIs

Si deseas continuar profundizando en Rate Limiting, sistemas distribuidos y arquitectura de APIs, te recomendamos los siguientes libros:

Keine Bücher für Kategorie "api-development" gefunden.

Volver al blog
Share:

Nächster Artikel in Desarrollo de API

Weiterlesen
gRPC, GraphQL y REST: Comparativa 2026

Entradas relacionadas