Saltar al contenido

Rate limiting en tu API: implementación práctica

6 min de lectura Software
  • rate limiting
  • api
  • seguridad
  • express
  • throttle

El rate limiting no es una funcionalidad extra en una API — es una medida de seguridad básica y un mecanismo de protección de recursos. Sin él, tu servicio es vulnerable a ataques de denegación de servicio (DoS), abusos o simplemente un mal uso que agota tus recursos de servidor. Implementarlo bien significa garantizar estabilidad y disponibilidad.

Por qué necesitas rate limiting en tu API

Los problemas comunes que resuelvo para clientes con APIs que no tienen rate limiting son siempre los mismos: picos de carga inesperados, costes de infraestructura disparados por peticiones excesivas o vulnerabilidades a bots que rastrean datos. Limitar el número de peticiones por usuario o IP en un periodo dado protege tu API de estos escenarios. Es un cortafuegos que gestiona el tráfico.

El rate limiting no solo protege contra ataques maliciosos, sino que también fomenta un uso responsable de tu API. Comunica claramente los límites y evita que un solo cliente consuma todos los recursos disponibles para el resto.

Estrategias de rate limiting y sus complejidades

Hay varias formas de implementar rate limiting. La más sencilla es la ventana fija (Fixed Window), que permite N peticiones en un periodo de tiempo, pero puede sufrir picos al principio y final de la ventana. Otra opción es la ventana deslizante por log (Sliding Window Log), que ofrece una distribución más suave y evita esos picos abruptos al contar peticiones de forma continua.

Cuando un cliente me llega con problemas de rendimiento en su API, lo primero que miro es si hay algún tipo de control de acceso. La diferencia entre una API robusta y una que se cae con facilidad no es solo la potencia del servidor — es la inteligencia en la gestión del tráfico. Entender qué estrategia se adapta mejor a tu patrón de uso es clave para una implementación efectiva.

Implementación práctica con Express.js

En un entorno Node.js con Express, usar una librería como express-rate-limit es el camino más directo para una implementación básica. Esta librería permite configurar políticas por ruta, por IP o incluso por clave de API, si tu sistema de autenticación lo permite. Mi regla es empezar siempre con lo más sencillo que resuelva el problema y luego iterar.

Aquí tienes un ejemplo de cómo aplicar rate limiting globalmente y luego una política específica para una ruta más sensible, como un /api/login:

const rateLimit = require('express-rate-limit');
const express = require('express');
const app = express();

// Rate limiter global para todas las peticiones
const globalLimiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutos
    max: 100, // Limita cada IP a 100 peticiones por windowMs
    message: 'Demasiadas peticiones desde esta IP, intenta de nuevo en 15 minutos.',
    standardHeaders: true, // Devuelve información de rate limit en los headers `RateLimit-*`
    legacyHeaders: false, // Deshabilita los headers `X-RateLimit-*`
});

// Rate limiter más estricto para una ruta de login
const loginLimiter = rateLimit({
    windowMs: 5 * 60 * 1000, // 5 minutos
    max: 5, // Limita cada IP a 5 intentos de login por windowMs
    message: 'Demasiados intentos de login fallidos desde esta IP, intenta de nuevo en 5 minutos.',
    standardHeaders: true,
    legacyHeaders: false,
});

// Aplica el rate limiter global a todas las rutas
app.use(globalLimiter);

// Aplica el rate limiter específico a la ruta de login
app.post('/api/login', loginLimiter, (req, res) => {
    // Lógica de login
    res.send('Login exitoso o fallido');
});

// Otras rutas con el limiter global
app.get('/api/data', (req, res) => {
    res.send('Datos de la API');
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Servidor Express escuchando en el puerto ${PORT}`);
});

Este código es un punto de partida para controlar el acceso a tus endpoints. Lo que sí es importante es monitorizar cómo se comporta tu API bajo estas restricciones, ajustando los límites según el tráfico real y las necesidades de tu servicio. Si estás viendo que tu API se comporta de forma inesperada en producción, es probable que haya un problema en la configuración del entorno, como explico en mi artículo sobre por qué tu código funciona en local y falla en producción.

Tradeoffs de implementar rate limiting

Implementar rate limiting siempre implica decidir qué priorizar: seguridad, rendimiento o una experiencia de usuario sin interrupciones. No hay una configuración universal que sirva para todos los casos; cada API tiene sus propias particularidades.

Lo que ganas:

  • Protección contra abusos: Mitiga ataques DoS, scraping y el uso excesivo de recursos por bots o usuarios malintencionados.
  • Estabilidad del servicio: Evita que picos de tráfico inesperados saturen tu servidor o base de datos, manteniendo la API operativa.
  • Control de costes: Reduce el consumo de recursos de computación y ancho de banda, lo que se traduce en ahorros directos en tu infraestructura.

Lo que complicas:

  • Falsos positivos: Usuarios legítimos pueden ser bloqueados si superan los límites por un uso intensivo pero válido, lo que impacta negativamente su experiencia.
  • Gestión del estado: Si tu API corre en múltiples instancias, coordinar el rate limiting entre ellas requiere una capa de almacenamiento centralizada (como Redis), añadiendo complejidad a la arquitectura.
  • Configuración y ajuste: Definir los límites adecuados es un proceso iterativo que requiere monitorización y un buen entendimiento del patrón de uso de tu API.
  • Latencia adicional: Aunque mínima, cada petición debe pasar por la lógica de rate limiting, lo que puede añadir una pequeña sobrecarga.

Lo que no negocias es la seguridad básica. Dejar una API expuesta sin rate limiting es como dejar la puerta de tu casa abierta en una ciudad concurrida.

Si te preocupa el rendimiento de tu API, entender cómo la caché en aplicaciones web puede ayudar o estorbar es el siguiente paso. Y para proteger tu API de manera más integral, considera implementar certificados SSL automáticos con Let’s Encrypt y Traefik para asegurar las comunicaciones. También, si buscas una capa extra de seguridad para el acceso a tus servicios internos, explora cómo Cloudflare Tunnel puede ser la única puerta de entrada a tu VPS.

Lucas Juárez
Lucas Juárez

Técnico freelance especializado en desarrollo a medida, automatizaciones con IA y gestión técnica para negocios en España. Más sobre mí →

Compartir:

¿Necesitas desarrollo a medida?

Desarrollo funcionalidades específicas, integraciones entre sistemas y herramientas internas. Si se puede programar, probablemente puedo hacerlo.

Chat