Redis más allá del caché: sesiones, límites de tasa, colas y Pub/Sub en Node.js
Siete patrones de Redis para backends en Node.js: caché con TTL, claves OTP, límites de tasa, trabajos BullMQ, sesiones, límites Pub/Sub, y cuándo no usar Redis.
Los modelos mentales iniciales tratan a Redis como “solo un caché”: almacenar un valor, establecer una fecha de vencimiento, leerlo más rápido que la base de datos, y listo.
Esa visión no está equivocada. Es incompleta.
En la práctica, Redis se utiliza para respuestas API rápidas, sesiones compartidas, contadores de abuso, códigos de un solo uso, colas de tareas diferidas, distribución en tiempo real ligera y otros valores de corta duración.
Un enfoque mejor: tratar a Redis como un almacén de datos en memoria rápido con muchas funciones de backend; el caché es solo la primera.
1. Redis puede hacer que una API sea mucho más rápida
Comience con el caché.
Considere GET /products.
Sin caché, cada solicitud podría seguir este flujo:
Cliente → API de Node.js → PostgreSQL → API de Node.js → Cliente
Una consulta costosa realizada miles de veces significa que la base de datos repite el mismo trabajo.
Redis puede interponerse antes de esa consulta.
Cliente → API de Node.js → Redis
En caso de éxito, devolver inmediatamente. En caso de fracaso, consultar PostgreSQL, almacenar el resultado en Redis y luego devolverlo.
Un ejemplo sencillo con ioredis:
import Redis from "ioredis";
const redis = new Redis(process.env.REDIS_URL);
async function getProducts() {
const cached = await redis.get("products");
if (cached) {
return JSON.parse(cached);
}
const products = await database.product.findMany();
await redis.set(
"products",
JSON.stringify(products),
"EX",
300
);
return products;
}h
Aquí EX significa que el contenido en caché expira después de 300 segundos.
Aún existe un problema importante: la invalidación de caché.
Supongamos que Redis almacena product:123 → price:500 mientras que PostgreSQL ahora guarda 600. La base de datos tiene la información correcta; sin embargo, Redis podría seguir mostrando 500.
El caché no significa “poner todo en Redis”. Los equipos aún deben considerar:
- TTLs
- Invalidación
- Datos obsoletos
- Fracasos en la búsqueda
- Fallas del caché
Poner un valor en Redis es fácil. Mantenerlo correcto es más complicado.
2. Redis es adecuado para datos temporales
Los valores de corta duración son una opción natural: códigos de inicio de sesión únicos, enlaces de restablecimiento, tokens de verificación, bloques de sesión efímeros, contadores de abuso y bloqueos de advertencia.
Ejemplo: emitir un código único:
const otp = "482913";
await redis.set(
`otp:${userId}`,
otp,
"EX",
300
);
El OTP expira automáticamente después de cinco minutos.
No se requiere una tabla dedicada para los OTP, ni tampoco tareas separadas de limpieza.
Se puede leer nuevamente con:
const otp = await redis.get(`otp:${userId}`);
Después del TTL, Redis elimina la clave según su mecanismo de vencimiento.
Ese patrón hace que Redis sea el lugar ideal para los datos de aplicaciones de corta duración.
3. Redis puede ayudar con la limitación de frecuencia
Tomemos POST /login.
Sin limitaciones, un cliente puede saturar los intentos de inicio de sesión: miles de solicitudes seguidas.
Redis puede mantener un contador para el cliente:
const key = `login-attempts:${ip}`;
const attempts = await redis.incr(key);
if (attempts === 1) {
await redis.expire(key, 60);
}
if (attempts > 10) {
throw new Error("Too many requests");
}
La estructura es: IP → contador de Redis → conteo → límite.
Esto es aún más importante cuando hay varios servidores API detrás de un balanceador de carga. Los contadores en memoria por proceso no son globales. Redis proporciona un almacenamiento compartido para esos servidores.
4. Redis puede gestionar tareas en segundo plano
La creación de cuentas puede requerir crear al usuario, enviar un correo de bienvenida, generar datos, notificar a otro servicio y realizar otras tareas.
La solicitud HTTP no debe esperar a que se realicen todas esas acciones.
En su lugar, envíe el trabajo a una cola:
Cliente → API → Cola → Respuesta
Luego:
Cola → Procesador → Ejecutar tarea
BullMQ es una opción común en Node.js que utiliza Redis:
await emailQueue.add("welcome-email", {
userId: user.id,
email: user.email,
});
Un procesador trabaja de forma independiente:
const worker = new Worker(
"email",
async (job) => {
if (job.name === "welcome-email") {
await sendWelcomeEmail(job.data.email);
}
},
{
connection: redisConnection,
}
);
La API no necesita esperar a que el proveedor de correos responda antes de responder al usuario.
Esto es adecuado para tareas lentas, reintentables, dependientes de servicios externos, que consumen muchos recursos del CPU o que no son necesarias antes de que la API responda.
Dividir las responsabilidades: la API se encarga de la solicitud; el proceso en segundo plano se ocupa del trabajo pesado.
5. Redis puede almacenar sesiones
La gestión de sesiones es otra aplicación adecuada. Una clave como session:abc123 podría contener:
{
"userId": "123",
"role": "ADMIN"
}
Esto resulta valioso cuando varias instancias del backend comparten un almacén de sesiones a través de Redis.
Diferencia importante: Redis no hace que la autenticación sea segura automáticamente.
Los equipos aún deben gestionar los identificadores de sesiones, las cookies seguras, la fecha de vencimiento, el CSRF cuando sea aplicable, así como la autenticación y autorización.
Redis es una infraestructura, no una estrategia de seguridad.
6. Redis puede ayudar con funciones en tiempo real
Pub/Sub permite distribuir eventos entre instancias. Un flujo típico consiste en que un cliente se conecte al servidor A, publique datos en Redis, un procesador de suscripciones en el servidor B los reciba y luego los envíe a otro cliente.
Illustración:
await redis.publish(
"notifications",
JSON.stringify({
userId: "123",
message: "Your order has shipped",
})
);
await subscriber.subscribe("notifications")
subscriber.on("message", (channel, message) => {
console.log(channel, message);
});
Útil para notificaciones, actualizaciones en tiempo real, flujos relacionados con chats y propagación de eventos.
Límite: Redis Pub/Sub no es una cola de mensajes duradera.
Si el procesamiento duradero, las reintentos o la entrega garantizada son importantes, prefiera una cola o Redis Streams según el caso.
Saber esa diferencia es crucial.
7. Redis se convierte en un problema si se utiliza en todas partes
La lección más importante: una vez que Redis está disponible, es tentador guardar todo allí.
No lo haga.
Solo la velocidad no significa que todos los datos deban estar en memoria.
PostgreSQL puede seguir siendo la fuente permanente de verdad para los datos empresariales, mientras que Redis se encarga del caché, sesiones, códigos OTP, límites de velocidad y colas.
Una división práctica mantiene los registros empresariales duraderos en PostgreSQL y reserva Redis para rutas de alto tráfico, tiempos de vida cortos y cargas de trabajo como colas o contadores.
Dibujar esa línea desde el principio evita numerosos rediseños posteriores.
Las estructuras de datos de Redis son importantes
Redis no es solo clave → cadena de texto. Ofrece varias estructuras.
Cadenas de texto
Valores simples, como user:123:name → “Mit”.
Hashes
Varios campos bajo una misma clave:
user:123
name → Mit
role → ADMIN
email → example@email.com
Listas
Colecciones ordenadas y algunos patrones similares a colas.
Conjuntos
Valores únicos.
Conjuntos ordenados
Elementos ordenados por puntuación; por ejemplo, una tabla de clasificación:
1000 → Player A
900 → Player B
800 → Player C
Elegir la estructura adecuada suele simplificar el problema.
Errores comunes en Redis que hay que evitar
Error 1: almacenar todo en caché
No toda consulta necesita un caché. El uso de cachés añade complejidad. Si una consulta ya es lo suficientemente rápida, Redis podría resolver un problema que en realidad no existe.
Error 2: falta de vencimiento
Los datos temporales sin plazos de vencimiento se acumulan. Si los datos no necesitan permanecer para siempre, establezca una política de vencimiento para ellos.
Error 3: tratar a Redis como la base de datos permanente
Si Redis alberga la única copia de los datos empresariales críticos, el sistema tiene una dependencia grave. Es necesario conocer la fuente de verdad de los datos.
Error 4: ignorar las fallas en Redis
Décida qué ocurrirá cuando Redis esté inactivo. Para muchos usos del caché, recurrir a la base de datos es aceptable. La estrategia adecuada depende del papel que desempeña Redis.
Error 5: usar Redis sin comprender la carga de trabajo
La velocidad no es infinita. Todavía hay que considerar aspectos como la memoria, el desalojo de datos, las conexiones, el diseño de claves, los TTL, la serialización, la latencia de red y las necesidades de persistencia.
Cómo Redis cambia la forma de pensar en los backends
Muchos diseños comienzan con un manejador de solicitudes que se comunica directamente con SQL.
Una vez que aparecen almacenes en memoria y trabajadores diferidos, el flujo suele ampliarse: el manejador primero verifica en Redis y luego en la base de datos; o bien coloca las tareas en una cola para que un trabajador se comunique con un proveedor externo.
Los backends pasan a ser colecciones de componentes especializados. Redis es uno de esos componentes que puede desempeñar más de un papel.
Conclusión
No adopte Redis solo porque todos los demás lo hacen.
Utilícelo cuando sea evidente la necesidad: caché para lecturas frecuentes, claves TTL para secretos de corta duración, contadores para límites de abuso, colas para tareas diferidas, un almacén de sesiones compartido entre instancias, o Pub/Sub cuando sea suficiente una distribución ligera.
Evite hacer de Redis la solución por defecto para cada problema relacionado con el backend.
Los buenos sistemas no son aquellos que cuentan con las listas más largas de herramientas. Son aquellos en los que cada herramienta merece su lugar.