Conceptos Básicos en Tiempo Real
10 ejemplos para elegir entre WebSocket, SSE y long-polling - 7 básicos y 3 intermedios.
Busca en todas las páginas de la documentación
10 ejemplos para elegir entre WebSocket, SSE y long-polling - 7 básicos y 3 intermedios.
Estos ejemplos asumen Node.js 24.18.0 y un servidor HTTP ya en ejecución (Express 5, Fastify 5 o node:http puro).
npm install ws
npm install -D @types/wsPara detalles de implementación, consulta Librería ws, Eventos Enviados por el Servidor y Socket.IO.
| Protocolo | Dirección | Transporte | Reconexión | Complejidad |
|---|---|---|---|---|
| WebSocket | Bidireccional | Actualización TCP | Manual | Media |
| SSE | Servidor a cliente | Flujo HTTP | Automática | Baja |
| Long-poll | Servidor a cliente | Petición HTTP | Manual | La más baja |
Usa WebSocket cuando:
- El cliente envía mensajes con frecuencia (chat, juegos, colaboración)
- La latencia debe ser < 50ms de ida y vuelta
- Datos binarios bidireccionales (audio, fragmentos de archivo)
- El estado de la conexión importa (presencia, indicadores de escritura)Usa SSE cuando:
- El servidor envía actualizaciones; el cliente solo envía a través de HTTP normal
- Feeds en vivo (precios de acciones, resultados deportivos, registros)
- Flujos de notificaciones
- Quieres reconexión automática del navegador// Encabezados de respuesta SSE
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
});
res.write("data: {\"price\": 142.50}\n\n");EventSource del navegador maneja la reconexión automáticamenteUsa long-polling cuando:
- La infraestructura bloquea WebSocket (proxies corporativos raros)
- Necesidad de notificación extremadamente simple
- Alternativa para Socket.IO (manejado automáticamente)| Caso de uso | Mejor opción | Por qué |
|---|---|---|
| Aplicación de chat | WebSocket | Bidireccional, baja latencia |
| Visor de registros en vivo | SSE | Envío del servidor, reconexión automática |
| Edición colaborativa | WebSocket | Sincronización de estado bidireccional |
| Cotización de acciones | SSE | Envío unidireccional, compatible con HTTP |
| Juego multijugador | WebSocket | Bidireccional, soporte binario |
| Insignia de notificación de correo electrónico | SSE o polling | Poco frecuente, unidireccional |
Ciclo de vida de WebSocket:
1. El cliente envía una petición de actualización HTTP
2. El servidor responde 101 Switching Protocols
3. Se establece una conexión TCP persistente
4. Se intercambian tramas bidireccionalmente
5. Cualquiera de las partes envía una trama de cierre
6. La conexión se termina
Ciclo de vida de SSE:
1. El cliente abre un GET HTTP (EventSource)
2. El servidor transmite text/event-stream
3. La conexión permanece abierta
4. El servidor envía líneas data:
5. Al desconectarse, el navegador se reconecta automáticamente// WebSocket: valida durante la actualización
server.on("upgrade", (req, socket, head) => {
const token = new URL(req.url!, "http://localhost").searchParams.get("token");
if (!isValid(token)) {
socket.write("HTTP/1.1 401 Unauthorized\r\n\r\n");
socket.destroy();
return;
}
wss.handleUpgrade(req, socket, head, (ws) => wss.emit("connection", ws, req));
});import express from "express";
import { createServer } from "node:http";
import { WebSocketServer } from "ws";
const app = express();
const server = createServer(app);
const wss = new WebSocketServer({ noServer: true });
server.on("upgrade", (req, socket, head) => {
if (req.url?.startsWith("/ws")) {
wss.handleUpgrade(req, socket, head, (ws) => {
wss.emit("connection", ws, req);
});
}
});
wss.on("connection", (ws) => {
ws.on("message", (data) => ws.send(`echo: ${data}`));
});
server.listen(3000);import Fastify from "fastify";
const app = Fastify();
app.get("/events", async (req, reply) => {
reply.raw.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
});
const interval = setInterval(() => {
reply.raw.write(`data: ${JSON.stringify({ time: Date.now() })}\n\n`);
}, 1000);
req.raw.on("close", () => clearInterval(interval));
});reply.raw para el control directo del flujo en FastifyAntes de 1000 conexiones concurrentes, planifica:
- Sesiones pegajosas (afinidad del balanceador de carga)
- Redis pub/sub para mensajería entre instancias
- Límites de conexión por instancia
- Latido/ping para detectar conexiones muertas
- Apagado elegante (notificar a los clientes, cerrar conexiones)SSE. Las notificaciones son de servidor a cliente. SSE ofrece reconexión automática y funciona a través de la infraestructura HTTP.
Sí. SSE funciona sobre HTTP/1.1 y HTTP/2. Deshabilita el almacenamiento en búfer del proxy en nginx.
Cuando necesites salas, retroceso automático y un adaptador de Redis para escalar. Consulta Socket.IO.
10k-50k conexiones inactivas dependiendo de la memoria. La distribución activa reduce esto. Perfila con tus patrones de mensajes.
No. Usa HTTP REST para CRUD. Agrega WebSocket/SSE solo para requisitos de envío en tiempo real.
Versiones de la pila: Esta página fue escrita para Node.js 24.18.0 (LTS Activo), npm 10+, TypeScript 5.6+, Express 5, Fastify 5 y NestJS 11.
Revisado por Chris St. John·Última actualización: 16 jul 2026