Añade funcionalidad en tiempo real a tu aplicación web: notificaciones push, chat, actualizaciones de dashboard y colaboración en vivo. Con la implementación de WebSockets, el manejo de reconexiones y los patrones de arquitectura para escalar sin servidor de estado.
Cuándo usarlo: WebSockets, tiempo real, notificaciones, chat, Redis
Herramienta recomendada: Claude
Eres un Backend Engineer con experiencia implementando sistemas de tiempo real en aplicaciones web con 10k-1M usuarios concurrentes. Mi contexto: - Stack: [Node.js / Python / PHP Laravel / Go / otro] - Framework frontend: [React / Vue / Svelte / vanilla JS / otro] - Funcionalidad de tiempo real que necesito: [notificaciones / chat / dashboard en vivo / colaboración / actualizaciones de estado / otro] - Escala: [<1.000 usuarios concurrentes / 1k-100k / >100k] - Infraestructura: [VPS único / múltiples servidores / Kubernetes / serverless] ## Tiempo Real en Aplicaciones Web — [Tu caso] ### 🧠 Elegir la tecnología correcta **WebSockets vs. Server-Sent Events (SSE) vs. Long Polling:** | Tecnología | Dirección | Cuándo usarla | |-----------|----------|---------------| | WebSockets | Bidireccional | Chat, colaboración en vivo, juegos | | SSE (Server-Sent Events) | Solo servidor→cliente | Notificaciones, dashboards, feeds | | Long Polling | Pseudo-tiempo real | Fallback o sistemas legacy | **La regla:** Si solo necesitas que el servidor avise al cliente → SSE (más simple, reconexión automática). Si el cliente también envía datos en tiempo real → WebSockets. ### 📡 Implementación con WebSockets **Backend — Node.js con ws:** ```javascript import { WebSocketServer } from 'ws' import http from 'http' const server = http.createServer() const wss = new WebSocketServer({ server }) // Mapa de conexiones activas: userId → ws const clients = new Map() wss.on('connection', (ws, req) => { const userId = getUserIdFromRequest(req) // desde JWT o cookie clients.set(userId, ws) ws.on('message', (data) => { const message = JSON.parse(data.toString()) handleMessage(userId, message) }) ws.on('close', () => { clients.delete(userId) }) ws.on('error', (err) => { console.error('WebSocket error:', err) clients.delete(userId) }) // Enviar estado inicial al conectar ws.send(JSON.stringify({ type: 'connected', userId })) }) // Función para enviar a un usuario específico function sendToUser(userId, data) { const client = clients.get(userId) if (client?.readyState === 1) { // 1 = OPEN client.send(JSON.stringify(data)) } } // Función para broadcast a todos function broadcast(data) { clients.forEach(client => { if (client.readyState === 1) { client.send(JSON.stringify(data)) } }) } ``` **Frontend — con reconexión automática:** ```javascript class RealtimeClient { constructor(url) { this.url = url this.ws = null this.reconnectDelay = 1000 this.maxDelay = 30000 this.listeners = new Map() this.connect() } connect() { this.ws = new WebSocket(this.url) this.ws.onopen = () => { console.log('Conectado') this.reconnectDelay = 1000 // reset delay } this.ws.onmessage = (event) => { const data = JSON.parse(event.data) const handler = this.listeners.get(data.type) handler?.(data) } this.ws.onclose = () => { // Reconexión exponencial con jitter setTimeout(() => this.connect(), this.reconnectDelay + Math.random() * 1000) this.reconnectDelay = Math.min(this.reconnectDelay * 2, this.maxDelay) } } on(type, handler) { this.listeners.set(type, handler) } send(data) { if (this.ws?.readyState === WebSocket.OPEN) { this.ws.send(JSON.stringify(data)) } } } // Uso: const rt = new RealtimeClient('wss://api.tuapp.com/ws') rt.on('notification', (data) => showNotification(data)) rt.on('dashboard_update', (data) => updateChart(data)) ``` ### 🔧 El problema de escalar WebSockets con múltiples servidores **El problema:** Si tienes 3 servidores y el usuario A está en el servidor 1, y el usuario B en el servidor 3, el servidor 1 no puede enviarle un mensaje al servidor 3 directamente. **La solución — Redis Pub/Sub:** ```javascript import Redis from 'ioredis' const pub = new Redis() const sub = new Redis() // Cada servidor se suscribe al canal sub.subscribe('realtime') sub.on('message', (channel, message) => { const { userId, data } = JSON.parse(message) // Si este servidor tiene la conexión de ese userId, envía const client = clients.get(userId) if (client?.readyState === 1) { client.send(JSON.stringify(data)) } }) // Para enviar desde cualquier servidor: function sendToUser(userId, data) { pub.publish('realtime', JSON.stringify({ userId, data })) } ``` ### 🚀 Alternativas gestionadas (cuando no quieres implementarlo tú) Ably, Pusher, Soketi (self-hosted Pusher) y cuándo tiene sentido usar uno en lugar de implementar WebSockets propios.