Limitación de Tasa en Node.js: Guía Completa para Proteger APIs y Gestionar la Carga

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Limitación de Tasa en Node.js: Protección de APIs contra Sobrecargas y Atacantes

\n\n

La limitación de tasa (rate limiting) es un mecanismo críticamente importante para cualquier aplicación web en Node.js. Permite controlar la cantidad de solicitudes que un cliente puede enviar al servidor en un período de tiempo determinado. Sin limitación de tasa, su API es vulnerable a ataques DDoS, sobrecargas accidentales y consumo excesivo de recursos.

\n\n

¿Por qué es necesaria la Limitación de Tasa?

\n
    \n
  • Protección contra fuerza bruta: Previene múltiples intentos de inicio de sesión.
  • \n
  • Prevención de DDoS: Limita el impacto de ataques de denegación de servicio.
  • \n
  • Distribución justa de recursos: Garantiza acceso equitativo para todos los usuarios.
  • \n
  • Ahorro de costos: Reduce la carga en servidores y bases de datos.
  • \n
  • Cumplimiento de SLA: Cumplimiento de acuerdos de nivel de servicio.
  • \n
\n\n

Algoritmos Principales de Limitación de Tasa

\n

Existen varios enfoques para implementar la limitación de velocidad. Veamos los más populares:

\n\n

1. Sliding Window (Ventana Deslizante)

\n

El algoritmo más común. Las solicitudes se agrupan en ventanas de tiempo (por ejemplo, 1 minuto). Si la cantidad de solicitudes supera el límite, las siguientes solicitudes se rechazan hasta que comience una nueva ventana.

\n\n

2. Token Bucket (Cubo de Fichas)

\n

Un "cubo" virtual contiene fichas. Cada solicitud consume una ficha. Las fichas se reponen a una velocidad fija. Si el cubo está vacío, la solicitud se rechaza.

\n\n

3. Leaky Bucket (Cubo con Fugas)

\n

Las solicitudes entran en una cola y se procesan a una velocidad constante. Si la cola se desborda, las solicitudes se descartan.

\n\n

Bibliotecas para Limitación de Tasa en Node.js

\n\n

1. express-rate-limit

\n

La biblioteca más popular para Express.js. Fácil de usar y configurable.

\n\n
const rateLimit = require('express-rate-limit');\n\n// Creamos un middleware para limitar solicitudes\nconst limiter = rateLimit({\n  windowMs: 15 * 60 * 1000, // 15 minutos\n  max: 100, // máximo 100 solicitudes por ventana\n  message: 'Demasiadas solicitudes, intente más tarde.',\n  standardHeaders: true, // Devuelve cabeceras RateLimit-*\n  legacyHeaders: false, // Desactiva cabeceras X-RateLimit-*\n});\n\n// Aplicamos a todas las rutas\napp.use(limiter);\n\n// O solo a una ruta específica\napp.use('/api/login', limiter);\n
\n\n

2. bottleneck

\n

Biblioteca universal que funciona con cualquier operación asíncrona. Soporta los algoritmos Token Bucket y Leaky Bucket.

\n\n
const Bottleneck = require('bottleneck');\n\n// Creamos un limitador: 5 solicitudes por segundo\nconst limiter = new Bottleneck({\n  minTime: 200, // 200 ms entre solicitudes\n  maxConcurrent: 5, // máximo 5 solicitudes simultáneas\n  reservoir: 100, // cantidad inicial de fichas\n  reservoirRefreshAmount: 100,\n  reservoirRefreshInterval: 60 * 1000, // recarga cada minuto\n});\n\n// Envolvemos la función en el limitador\nasync function fetchData(url) {\n  const response = await fetch(url);\n  return response.json();\n}\n\nconst limitedFetch = limiter.wrap(fetchData);\n\n// Uso\nconst data = await limitedFetch('https://api.example.com/data');\n
\n\n

3. rate-limiter-flexible

\n

Biblioteca flexible con soporte para Redis, MongoDB, Memcached y otros almacenes. Ideal para sistemas distribuidos.

\n\n
const { RateLimiterRedis } = require('rate-limiter-flexible');\nconst Redis = require('ioredis');\n\nconst redisClient = new Redis();\n\nconst rateLimiter = new RateLimiterRedis({\n  storeClient: redisClient,\n  keyPrefix: 'middleware',\n  points: 10, // 10 solicitudes\n  duration: 1, // por 1 segundo\n});\n\napp.use(async (req, res, next) => {\n  try {\n    await rateLimiter.consume(req.ip);\n    next();\n  } catch (rejRes) {\n    res.status(429).send('Demasiadas solicitudes');\n  }\n});\n

Recommendations