API Protection

Rate Limiting

El rate limiting protege una API contra el abuso, errores y clientes descontrolados. Algunos algoritmos y encabezados claros mantienen tu servicio disponible para todos.

intermediate14 min readUpdated 15 sept 2026
limit.js
js
// limit.js
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";

const ratelimit = new Ratelimit({
  redis: Redis.fromEnv(),
  limiter: Ratelimit.slidingWindow(100, "1 m"),
});

export async function handler(req, res) {
  const id = req.headers["x-api-key"] ?? req.ip;
  const { success, remaining, reset } = await ratelimit.limit(id);

  res.set("RateLimit-Remaining", String(remaining));
  res.set("RateLimit-Reset", String(Math.ceil(reset / 1000)));

  if (!success) {
    res.set("Retry-After", "60");
    return res.status(429).json({ error: "rate_limited" });
  }
  // ...handle the request
}
Estado
429 Too Many Requests
Sugerencia
Encabezado Retry-After
Identidad
Clave, usuario o IP
Algoritmos
Window, bucket
Almacenamiento
Redis para múltiples instancias
Objetivo
Disponibilidad para todos

Por que importa

Por qué aplicar rate limiting

Proteger la disponibilidad

Un solo cliente con mal comportamiento o un bot de scraping puede agotar tu capacidad. Los límites mantienen el servicio activo para todos los demás.

Uso justo

Los límites por clave y por nivel aseguran que un solo llamador no pueda consumir más de lo que le corresponde.

Limitar el daño

Los límites también topan el costo de los errores, como un cliente atrapado en un bucle de reintentos bombardeando tu API.

La imagen completa

Las tres ideas detrás del rate limiting

Identificar al cliente, contar sus solicitudes con un algoritmo e informarle lo sucedido con el estado y los encabezados correctos.

Identidad

Contar

Decidir bajo qué criterio se cuenta una solicitud: una clave de API, un usuario, una IP o una combinación.

Algoritmo

Limitar

Fixed window, sliding window, token bucket o leaky bucket deciden cómo se permiten las solicitudes.

Respuesta

Señalizar

Devolver un 429 con Retry-After y encabezados de rate limit para que los clientes puedan reducir la frecuencia de sus peticiones correctamente.

Rate limiting de un vistazo

Las ideas centrales

Fixed window

Un contador simple que se reinicia cada intervalo; económico pero permite ráfagas en el límite de la ventana.

Sliding window

Suaviza el problema del límite de ventana con mayor precisión.

Token bucket

Permite ráfagas hasta el tamaño del bucket mientras impone una tasa promedio.

Leaky bucket

Procesa a una tasa constante y encola o descarta el exceso.

429 y Retry-After

La forma estándar de decir "ve más despacio, inténtalo más tarde".

Estado distribuido

Compartir contadores en Redis para que los límites se apliquen en todas las instancias.

Una breve historia

De los bloqueos de IP a los limitadores distribuidos

  1. 2000s

    Bloqueo basado en IP

    Las primeras defensas bloqueaban IPs abusivas a posteriori.

    2000s
  2. 2010s

    Claves de API y cuotas

    Las APIs públicas introducen límites por clave y cuotas mensuales.

    2010s
  3. 2015

    Limitadores con Redis

    Los contadores compartidos hacen que la limitación funcione a través de muchos servidores.

    15
  4. 2020

    Encabezados estándar

    Se proponen los encabezados RateLimit para hacer que los límites sean descubribles.

    20
  5. Today

    Defensas en capas

    Límites, cuotas, WAFs y detección de bots trabajan en conjunto.

    Today

La guia completa

Rate Limiting: Todo lo que necesitas saber

Por qué implementar rate limiting

Cada API tiene una capacidad finita y no todos los clientes se comportan correctamente. Un scraper, un cliente con errores atrapado en un bucle de reintentos o un pico de tráfico legítimo pueden agotar las conexiones de tu base de datos y dejar el servicio fuera de línea para todos. El rate limiting limita la velocidad a la que un cliente puede realizar solicitudes para que ningún usuario individual pueda consumir todos los recursos del sistema.

También hace que los costos sean predecibles, garantiza el uso justo entre tenants y planes, y te proporciona una herramienta para frenar el abuso antes de que se convierta en una caída del servicio.

Qué limitar

Un límite solo tiene sentido en relación con una identidad. Algunas opciones comunes son:

  • API key — la mejor opción para comunicaciones server-to-server y clientes de terceros.
  • User id — lo más natural para aplicaciones con autenticación.
  • IP address — una alternativa para el tráfico anónimo, aunque muchos usuarios pueden compartir la misma.
  • Combinación — clave más IP, o usuario más endpoint, para mayor precisión.
  • Endpoint o tier — límites más estrictos para operaciones costosas, como búsquedas o exportaciones.

También debes decidir el alcance: un límite global, un límite por endpoint, o ambos. Un límite global protege el servicio; los límites por endpoint protegen tareas específicas que consumen muchos recursos.

Algoritmos

Cuatro algoritmos cubren casi cualquier necesidad.

Fixed window — cuenta las solicitudes en un intervalo fijo y se reinicia al llegar al límite.

limit: 100 per minute
key: client:123:2026-09-15T10:05

Es económico y sencillo, pero un cliente puede enviar 100 solicitudes al final de una ventana y otras 100 al inicio de la siguiente, duplicando efectivamente la tasa en el límite.

Sliding window — cuenta durante los últimos N segundos en lugar de un bloque fijo, generalmente combinando la ventana actual y la anterior mediante un promedio ponderado. Es más fluido que el fixed window con un coste similar.

Token bucket — un cubo se rellena a un ritmo constante y cada solicitud consume un token. Permite ráfagas cortas hasta el tamaño del cubo mientras mantiene una tasa promedio, lo cual coincide con el comportamiento de los clientes reales.

// token-bucket.js
const capacity = 20;
const refillPerSecond = 5;
let tokens = capacity;
let last = Date.now();

function allow() {
  const now = Date.now();
  tokens = Math.min(capacity, tokens + ((now - last) / 1000) * refillPerSecond);
  last = now;
  if (tokens < 1) return false;
  tokens -= 1;
  return true;
}

Leaky bucket — las solicitudes entran en una cola que se vacía a un ritmo fijo. Suaviza el tráfico para obtener una salida constante, lo cual es útil cuando los sistemas downstream necesitan una carga estable.

Cómo responder a los límites

Informa a los clientes sobre lo que está sucediendo mediante señales estándar.

HTTP/1.1 429 Too Many Requests
Retry-After: 30
RateLimit-Limit: 100
RateLimit-Remaining: 0
RateLimit-Reset: 30
  • 429 Too Many Requests es el código de estado correcto.
  • Retry-After indica al cliente cuándo intentar de nuevo, ya sea en segundos o con una fecha.
  • Los encabezados RateLimit-* exponen el límite, el recuento restante y el tiempo de reinicio para que los clientes puedan regular su ritmo.

Devolver 200 o descartar solicitudes silenciosamente oculta el problema y provoca errores misteriosos en el cliente. Los clientes bien implementados leen Retry-After y reducen la frecuencia de sus peticiones automáticamente.

Limitación distribuida

Si ejecutas más de una instancia, los contadores deben compartirse. Los límites en memoria se aplican por instancia, por lo que con diez servidores, un cliente obtiene efectivamente diez veces el límite.

// redis.js
const key = `ratelimit:${apiKey}`;
const count = await redis.incr(key);
if (count === 1) await redis.expire(key, 60);

if (count > 100) {
  // reject with 429
}

Utiliza operaciones atómicas, o una librería que use un script de Lua, para que los incrementos y los tiempos de expiración estén libres de condiciones de carrera (race-free). Redis es el almacenamiento habitual porque es rápido y soporta scripts atómicos y expiración. Los API gateways y las plataformas edge pueden aplicar los límites antes incluso de que el tráfico llegue a tu aplicación, que es el lugar más eficiente para hacerlo.

Cuotas frente a límites de tasa (rate limits)

Resuelven problemas diferentes y a menudo coexisten.

  • Rate limit — qué tan rápido: 100 solicitudes por minuto.
  • Cuota — cuánto en total: 100,000 solicitudes por mes, vinculadas a un plan.

Un cliente puede mantenerse por debajo de su rate limit durante todo el mes y aun así agotar su cuota. Rastrea las cuotas por separado, generalmente con un contador de mayor duración, y devuelve un error específico cuando una cuota se haya agotado para que los clientes conozcan la diferencia.

Evitar afectar a los usuarios reales

Los límites deben detener el abuso sin penalizar el uso normal.

  • Establece los límites basándote en el tráfico medido, dejando un margen para picos de demanda.
  • Permite ráfagas de tráfico mediante un token bucket en lugar de un corte abrupto.
  • Utiliza límites diferentes por nivel de suscripción y por endpoint.
  • Excluye los health checks, las llamadas internas y los assets estáticos.
  • Prioriza las ralentizaciones temporales frente a los baneos permanentes.
  • Monitorea las tasas de rechazo y ajusta los valores; un pico de errores 429 puede indicar que un límite es demasiado restrictivo.

Mejores prácticas

  • Identifica a los clientes utilizando la clave estable más específica disponible.
  • Elige un algoritmo que se adapte a la forma del tráfico.
  • Devuelve un error 429 con Retry-After y los encabezados de rate limit.
  • Comparte los contadores en Redis o aplica los límites en el edge.
  • Separa los rate limits de las cuotas y expón ambos.
  • Permite ráfagas (bursts) y establece los límites basándote en mediciones reales.
  • Registra y monitorea los rechazos, y configura alertas para picos repentinos.

Errores comunes

  • Contar por instancia y multiplicar el límite efectivo.
  • Utilizar únicamente la IP, lo que penaliza a los usuarios detrás de un NAT compartido.
  • Devolver un código 200 o descartar las solicitudes silenciosamente.
  • Establecer límites tan estrictos que se bloqueen los clientes normales.
  • Olvidar expirar los contadores, provocando fugas de memoria.
  • Tratar los rate limits como un sustituto de la autenticación y la autorización.

Próximos pasos

El rate limiting mantiene una API disponible bajo presión. Basalo en el diseño REST y la guía de HTTP, combínalo con el versionado de API como parte del ciclo de vida e impleméntalo en Node.js. Después, añade un limitador a un endpoint y observa cómo se comporta bajo una prueba de carga.

Rechazar una solicitud

Devuelve un 429 con una sugerencia Retry-After y el conteo restante. Descartar la petición silenciosamente o devolver un 200 confunde a los clientes y oculta el problema.

Preferir
HTTP/1.1 429 Too Many Requests
Retry-After: 30
RateLimit-Limit: 100
RateLimit-Remaining: 0
RateLimit-Reset: 30
Evitar
HTTP/1.1 200 OK
# silently ignored or
# returns an empty body

Almacenar contadores

Con múltiples instancias, los contadores deben ser compartidos. Los límites en memoria se aplican por instancia y permiten que los clientes obtengan N veces la tasa prevista.

Preferir
const { success } = await ratelimit.limit(key);
// shared across every instance
Evitar
const counts = new Map();
// each server has its own map,
// so the real limit is N x

Compromisos

¿Es el rate limiting la defensa correcta?

Los límites protegen la disponibilidad y acotan el abuso, pero añaden estado y pueden castigar a usuarios legítimos si la identidad o los umbrales son incorrectos.

Strengths

  • Mantiene el servicio en pie

    Un cliente desbocado o un scraper no puede agotar la capacidad, así que todos los demás siguen siendo atendidos.

  • Reparto justo

    Los límites por clave y por nivel impiden que un solo llamador consuma más de su parte de un recurso compartido.

  • Acota el coste de los errores

    Un cliente atrapado en un bucle de reintentos se contiene antes de convertirse en una caída o en una factura elevada.

Trade-offs

  • Necesita estado compartido

    Unos límites correctos entre instancias requieren Redis o una pasarela, lo que añade una dependencia en la ruta crítica.

  • Fácil de equivocarse

    Unos límites demasiado ajustados o la identidad equivocada rechazan a usuarios reales, y los límites por IP castigan a todos los que hay detrás de un NAT.

  • No es una defensa completa

    Limitar por sí solo no detiene ataques distribuidos, así que funciona mejor junto a cuotas, WAF y detección de bots.

Preguntas frecuentes

Preguntas frecuentes

Keep learning

Related topics from the roadmap.

$ comienza a aprender

Listo para aprender Rate Limiting?

Nuestro tutorial interactivo te guia a traves de Rate Limiting paso a paso — con quizzes y codigo real que puedes ejecutar en el navegador.