WebSockets en Tiempo Real sin Redis: Usando Cloudflare Durable Objects en Nuxt 4
Construir funcionalidades en tiempo real (como notificaciones instantáneas, cursores colaborativos o dashboards en vivo) siempre ha sido una de las mayores pesadillas de las arquitecturas serverless.
Tradicionalmente, la receta para soportar WebSockets exigía:
- Un clúster de servidores Node.js dedicados siempre encendidos.
- Un clúster de Redis con Pub/Sub para sincronizar mensajes entre instancias.
- Un balanceador de carga configurado para conexiones persistentes (Sticky Sessions).
El costo mensual de esta infraestructura mínima rara vez bajaba de cientos de dólares. Nuxfire resuelve este desafío utilizando Cloudflare Durable Objects.
¿Qué son los Cloudflare Durable Objects?
Los Durable Objects ofrecen cómputo serverless con estado coordinado. Cada objeto se ejecuta como una instancia única en la red global de Cloudflare, lo que garantiza que todas las conexiones al mismo "canal" o "sala" lleguen al mismo proceso en memoria.
Además, cada Durable Object tiene su propia base de datos SQLite embebida, que permite persistir el historial de mensajes con una latencia inferior a 1 milisegundo.
[Usuario A (Navegador)] ──WebSockets──> ┌────────────────────────────────┐
│ Cloudflare Durable Object │
[Usuario B (Navegador)] ──WebSockets──> │ - Estado de conexiones en RAM │
│ - Base SQLite Embebida │
[Webhook / Worker Backend] ──Fetch────> └────────────────────────────────┘
Seguridad Robusta: Handshake con Tickets Firmados con HMAC
Las conexiones WebSocket no transmiten los headers HTTP normales después del handshake inicial. Para garantizar la máxima seguridad frente a conexiones falsificadas, Nuxfire utiliza tickets firmados criptográficamente:
- El cliente hace una petición HTTP autenticada solicitando un ticket de conexión.
- El servidor genera un token con HMAC firmado con la clave secreta de la aplicación y con una validez de 60 segundos.
- El cliente abre la conexión WebSocket pasando el ticket en la query string.
- El Durable Object valida la firma antes de aceptar el handshake.
// Generando el ticket firmado en el endpoint de autenticación
export function generateWebSocketTicket(userId: string, workspaceId: string) {
const expiresAt = Date.now() + 60 * 1000;
const payload = `${userId}:${workspaceId}:${expiresAt}`;
const signature = createHmac("sha256", env.WS_SECRET).update(payload).digest("hex");
return `${payload}:${signature}`;
}
Consumiéndolo en el Frontend con Composables de Nuxt
En el lado del cliente Nuxt 4, conectarse al canal del equipo es tan simple como usar un composable nativo:
<script setup lang="ts">
const { messages, status, send } = useTeamWebSockets();
function handleNotify() {
send({ type: "TEAM_PING", content: "¡Nueva tarea creada en el tablero!" });
}
</script>
<template>
<div>
<UBadge :color="status === 'OPEN' ? 'success' : 'neutral'">
{{ status === 'OPEN' ? 'Tiempo Real Activo' : 'Reconectando...' }}
</UBadge>
<div v-for="msg in messages" :key="msg.id">
{{ msg.content }}
</div>
</div>
</template>
Conclusión: Tiempo Real de Nivel Enterprise a tu Alcance
Con los Durable Objects, eliminas por completo los costos de los servidores Redis y Socket.io y aprovechas la red global de Cloudflare para ofrecer una experiencia ultrarrápida a tus usuarios.
Todo este flujo — desde los workers de backend hasta los composables reactivos de Nuxt — ya viene 100 % implementado y probado en Nuxfire.
Asegura tu licencia vitalicia y descarga el código ahora mismo →