SkillsTecnológicas
Menu
Back-end

SSE vs. WebSockets: diferenças e quando usar cada tecnologia

Compare SSE e WebSockets, entenda comunicação unidirecional e bidirecional, reconexão, escalabilidade e quando usar cada tecnologia.

Marcos RodriguesPublicado em 19 de agosto de 2026Atualizado em 16 de agosto de 202612 min de leitura
Servidor compara fluxo unidirecional de eventos com comunicação bidirecional entre navegadores

Uma tela precisa mostrar o progresso de uma tarefa, receber notificações ou exibir a resposta de uma inteligência artificial enquanto ela é gerada. Surge então a dúvida: usar SSE vs. WebSockets?

As duas tecnologias mantêm comunicação contínua com o servidor, mas resolvem problemas diferentes.

Server-Sent Events é a escolha mais simples quando os dados fluem principalmente do servidor para o cliente.

WebSockets fazem sentido quando cliente e servidor precisam trocar mensagens a qualquer momento, com baixa latência e pelo mesmo canal.

Essa diferença de direção costuma ser mais importante que a popularidade de cada tecnologia.

Neste guia, você verá como cada opção funciona, exemplos em JavaScript, reconexão, autenticação, proxies, escalabilidade, backpressure e uma matriz prática para escolher sem complicar a arquitetura.

O que é SSE?

SSE significa Server-Sent Events, ou eventos enviados pelo servidor. O navegador abre uma requisição HTTP persistente, e o servidor mantém a resposta aberta para transmitir novos eventos sempre que houver informação disponível.

O fluxo é unidirecional: servidor para cliente. Caso o navegador precise enviar um comando, pode usar uma requisição HTTP normal.

Essa combinação funciona bem quando a aplicação recebe muitas atualizações, mas envia poucas ações.

O HTML Living Standard define Server-Sent Events e a interface EventSource. A conexão usa o tipo de conteúdo text/event-stream, e cada evento é descrito em linhas de texto UTF-8.

Como Server-Sent Events funciona

O cliente cria um EventSource apontando para uma URL. O servidor responde com os cabeçalhos corretos e não encerra a resposta. Cada mensagem termina com uma linha em branco:

id: tarefa-42-7
event: progresso
data: {"percentual":70}

  • data contém o conteúdo entregue ao cliente.
  • event define um tipo de evento opcional.
  • id identifica a última mensagem processada.
  • retry pode sugerir o intervalo de reconexão em milissegundos.
  • Linhas iniciadas por dois-pontos podem funcionar como comentários e manter a conexão ativa.

Se a conexão cair, EventSource tenta reconectar automaticamente. Quando existe um ID, o navegador pode enviar Last-Event-ID na nova requisição.

O servidor precisa armazenar ou reconstruir os eventos caso queira reenviar o que foi perdido; a API sozinha não cria esse histórico.

Exemplo de SSE no servidor e navegador

Este servidor Node.js mínimo cria um evento de progresso a cada segundo:

import http from "node:http";

http.createServer((req, res) => {
  if (req.url !== "/eventos") {
    res.writeHead(404).end();
    return;
  }

  res.writeHead(200, {
    "Content-Type": "text/event-stream; charset=utf-8",
    "Cache-Control": "no-cache"
  });

  res.write("retry: 5000\n\n");
  let percentual = 0;

  const timer = setInterval(() => {
    percentual += 10;
    res.write(`id: ${percentual}\n`);
    res.write("event: progresso\n");
    res.write(`data: ${JSON.stringify({ percentual })}\n\n`);

    if (percentual === 100) {
      clearInterval(timer);
      res.end();
    }
  }, 1000);

  req.on("close", () => clearInterval(timer));
}).listen(3000);

No navegador, o consumo usa a API nativa:

const eventos = new EventSource("/eventos");

eventos.addEventListener("progresso", (evento) => {
  const dados = JSON.parse(evento.data);
  console.log(dados.percentual);
});

eventos.onerror = () => {
  console.log("Conexão interrompida; o navegador tentará novamente.");
};

Em produção, valide autenticação, cancelamento, heartbeat, limite de fila e comportamento do proxy.

Quem está começando no servidor pode revisar quando usar Node.js no back-end antes de transformar o exemplo em uma aplicação completa.

Servidor envia uma sequência contínua de eventos para uma interface web com reconexão

O que é WebSocket?

WebSocket é um protocolo de comunicação bidirecional. Depois que a conexão é estabelecida, cliente e servidor podem enviar mensagens independentemente, sem iniciar uma nova requisição HTTP para cada troca.

O RFC 6455 define o protocolo WebSocket como um handshake inicial seguido por enquadramento de mensagens sobre uma conexão TCP.

A API usada por aplicações web é mantida no WebSockets Living Standard.

Ao contrário do SSE, WebSocket aceita mensagens de texto e binárias.

Ele é apropriado quando o cliente também precisa publicar eventos frequentes: movimento em um jogo, alterações colaborativas, áudio, telemetria de controle ou mensagens de chat.

Como WebSocket funciona

No cenário clássico sobre HTTP/1.1, o cliente inicia um handshake HTTP solicitando a mudança de protocolo.

Se o servidor aceitar, responde com o status apropriado e a comunicação passa a usar frames WebSocket. Aplicações públicas devem usar wss://, protegido por TLS.

A partir daí, a aplicação define seu próprio protocolo de mensagens. Um campo type, por exemplo, pode distinguir presença, chat e confirmação.

Também é preciso decidir formato, versionamento, correlação, autorização, erros, reenvio e ordem dos eventos.

WebSocket entrega um canal, não uma arquitetura pronta. Bibliotecas podem acrescentar salas, reconexão e fallback, mas essas funções não fazem parte automaticamente da interface básica do navegador.

Exemplo de WebSocket no navegador

const socket = new WebSocket("wss://api.exemplo.com/tempo-real");

socket.addEventListener("open", () => {
  socket.send(JSON.stringify({
    type: "entrar",
    canal: "pedido-42"
  }));
});

socket.addEventListener("message", (evento) => {
  const mensagem = JSON.parse(evento.data);
  console.log(mensagem);
});

socket.addEventListener("close", (evento) => {
  console.log("Conexão encerrada", evento.code);
});

Uma implementação real deve validar cada mensagem e usar estados como CONNECTING, OPEN, CLOSING e CLOSED.

O cliente também precisa implementar reconexão com espera progressiva e variação aleatória para evitar que milhares de dispositivos retornem ao mesmo tempo.

Servidor troca dados nos dois sentidos com notebook, tablet e smartphone

SSE vs. WebSockets: comparação direta

CritérioSSEWebSockets
DireçãoServidor para clienteBidirecional
BaseResposta HTTP persistenteProtocolo WebSocket após handshake
Formato nativoTexto UTF-8Texto ou binário
API do navegadorEventSourceWebSocket
ReconexãoAutomática na API nativaImplementada pela aplicação
RetomadaSuporte a ID do último eventoProtocolo próprio
Envio do clienteOutra requisição HTTPNo mesmo canal
Cabeçalhos personalizados no navegadorLimitados no EventSource nativoLimitados no construtor nativo
Integração com infraestrutura HTTPGeralmente mais simples, mas exige evitar bufferingExige suporte ao upgrade ou mecanismo equivalente
Melhor encaixeFeeds, progresso, notificações e streaming de textoChat intenso, colaboração, jogos e controle em tempo real

Quando usar SSE

  • Progresso de importações, relatórios e tarefas em segundo plano.
  • Notificações e atualizações de status.
  • Feeds de eventos, auditoria ou observabilidade.
  • Painéis em que o servidor publica métricas periodicamente.
  • Streaming de texto quando uma requisição GET é suficiente.
  • Aplicações que desejam reconexão nativa e semântica de último evento.

SSE permite manter comandos em uma API REST e reservar o fluxo persistente apenas para atualizações.

Isso preserva logs, autorização e escalabilidade HTTP em operações comuns.

Quando usar WebSockets

  • Chats com troca frequente, presença e digitação.
  • Editores colaborativos e sincronização de cursores.
  • Jogos multiplayer e atualizações rápidas de estado.
  • Controle remoto, telemetria interativa e dispositivos.
  • Transferência de mensagens binárias.
  • Protocolos de aplicação em que ambos os lados publicam continuamente.

A frequência e a simetria importam. Se o usuário envia um comando ocasional e recebe centenas de atualizações, SSE mais HTTP pode continuar sendo a solução menor.

Se as duas direções carregam eventos contínuos, WebSocket reduz a necessidade de canais separados.

SSE em streaming de respostas de IA

Respostas de IA são frequentemente unidirecionais após o envio do prompt: o cliente envia a solicitação e o servidor devolve partes do texto.

O formato SSE é conveniente para separar eventos como início, fragmento, referência, erro e conclusão.

Há uma distinção importante. A API nativa EventSource abre uma requisição GET e não permite definir cabeçalhos arbitrários.

Se o prompt precisa seguir no corpo de um POST ou usar autorização personalizada, muitas implementações recorrem a fetch e leem um ReadableStream.

O servidor pode enviar um formato inspirado em SSE, mas o cliente está consumindo streaming de fetch, não um EventSource tradicional.

Nosso guia sobre streaming de respostas de IA no Next.js aprofunda o fluxo entre servidor e interface.

A decisão deve considerar cancelamento, tratamento de erro, moderação e o que acontece se a conexão cair no meio da geração.

Um chat precisa mesmo de WebSockets?

Nem sempre. Um chat de suporte com baixa frequência pode enviar mensagens por POST e receber novas mensagens por SSE.

Essa separação simplifica o servidor e mantém cada envio como uma operação HTTP observável.

WebSocket se torna atraente quando o produto inclui presença, indicador de digitação, confirmação rápida, múltiplas salas, chamadas frequentes e outros eventos nos dois sentidos.

Mesmo assim, documente o protocolo e não misture mensagens sem versionamento.

Reconexão e garantia de entrega

Conexões caem quando o dispositivo troca de rede, o navegador suspende a aba, um proxy encerra ociosidade ou uma implantação reinicia o servidor. Projetar reconexão não é opcional.

SSE tenta reconectar automaticamente e oferece o último ID como ponto de retomada.

Para isso funcionar, o servidor precisa manter um log de eventos por algum período e decidir o que fazer quando o ID já expirou: enviar um estado completo, recomeçar ou informar que a sincronização precisa ser refeita.

Em WebSocket, defina espera progressiva, jitter, heartbeat e ressincronização.

Depois de reconectar, o cliente não deve presumir que recebeu tudo. Pode enviar a última versão conhecida ou solicitar um snapshot.

Nenhuma das tecnologias garante exatamente uma entrega por conta própria; duplicação e idempotência pertencem ao protocolo da aplicação.

Proxies, timeouts e infraestrutura

Uma aplicação funcionar em localhost não prova que funcionará atrás de CDN, gateway e balanceador.

Para SSE, desative buffering da resposta onde necessário, envie cabeçalhos adequados e use heartbeats em intervalos compatíveis com o timeout de ociosidade.

Compressão também deve ser testada, pois pode acumular dados antes de liberá-los.

Com WebSocket, confirme suporte ao handshake, duração máxima, drenagem de conexões durante deploy e encaminhamento de frames.

O NGINX como proxy reverso, por exemplo, precisa ser configurado de acordo com a tecnologia e os limites da plataforma.

A documentação da MDN sobre SSE observa que conexões sobre HTTP/1.1 podem esbarrar no limite baixo de conexões simultâneas por navegador e domínio.

Com HTTP/2, o número de streams é negociado, reduzindo esse problema. Ainda assim, evite abrir um fluxo por componente: prefira uma conexão por aplicação e distribua eventos internamente.

Como escalar conexões persistentes

Milhares de conexões abertas consomem descritores, memória e capacidade de rede, mesmo quando quase não transmitem dados.

Meça conexões por instância, bytes por segundo, duração, filas, desconexões e tempo de reconexão.

  • Separar produção e entrega: serviços de negócio publicam eventos em um broker; gateways mantêm conexões com clientes.
  • Evitar estado local indispensável: qualquer instância deve reconstruir a assinatura ou consultar um armazenamento compartilhado.
  • Planejar deploy: retirar a instância do balanceador, drenar conexões e orientar reconexão.
  • Controlar fan-out: agrupar assinantes e não repetir consultas caras para cada conexão.
  • Limitar o cliente: aplicar cotas por usuário, organização, IP e canal.

Em arquiteturas de microsserviços, não faça cada serviço abrir conexões públicas. Um gateway de tempo real pode autenticar clientes, gerenciar assinaturas e consumir eventos internos.

Backpressure e clientes lentos

Backpressure é a capacidade de reagir quando o produtor envia dados mais rápido do que o consumidor processa.

Sem controle, filas crescem, memória aumenta e mensagens ficam obsoletas.

A documentação da API WebSocket na MDN alerta que a interface tradicional não oferece backpressure automático para mensagens recebidas.

No envio, bufferedAmount ajuda a observar quantos bytes ainda aguardam transmissão, mas a aplicação precisa definir limites e políticas.

  • Descarte estados intermediários quando apenas o valor mais novo importa.
  • Agrupe métricas em janelas em vez de enviar cada alteração.
  • Pause ou desconecte clientes que excedam filas seguras.
  • Separe eventos críticos de atualizações descartáveis.
  • Limite tamanho e frequência das mensagens em ambas as direções.

Segurança e autenticação

Use HTTPS e WSS. Autentique a abertura da conexão, autorize cada assinatura e reavalie permissões quando o usuário muda de canal.

Uma conexão autenticada não concede acesso automático a todo evento.

  • Valide Origin e configure CORS de forma explícita para SSE entre origens.
  • Evite tokens duradouros na query string, pois URLs podem aparecer em logs e históricos.
  • Se usar cookies, considere CSRF, SameSite, origem e escopo da sessão.
  • Defina expiração, renovação e revogação sem depender de uma conexão eterna.
  • Valide esquema, tamanho e frequência de cada mensagem WebSocket.
  • Não envie segredos para canais que o cliente não está autorizado a acompanhar.

As mesmas boas práticas para APIs seguras e escaláveis continuam válidas: menor privilégio, limites, registros de auditoria, validação de entrada e tratamento previsível de erros.

Checklist para tomar a decisão

  1. Mapeie a direção: o cliente publica eventos continuamente ou apenas recebe?
  2. Defina o formato: texto é suficiente ou existe conteúdo binário?
  3. Classifique a frequência: quantas mensagens cada lado envia por segundo?
  4. Desenhe a retomada: como recuperar estado após uma queda?
  5. Teste a infraestrutura: CDN, proxy, balanceador e plataforma aceitam a duração desejada?
  6. Modele segurança: como autenticar, autorizar canais e revogar acesso?
  7. Planeje clientes lentos: qual é o limite da fila e o que pode ser descartado?
  8. Meça uma solução simples: compare SSE, WebSocket e polling com carga representativa.

Se os eventos são unidirecionais, textuais e toleram o modelo HTTP, comece por SSE.

Se a interação é genuinamente bidirecional e frequente, escolha WebSocket.

Quando o requisito ainda é incerto, polling com intervalo moderado pode ser a linha de base mais barata.

Perguntas frequentes

SSE é realmente comunicação em tempo real?

Sim, no sentido de entregar atualizações assim que o servidor as disponibiliza por uma conexão aberta. A latência real depende da aplicação, rede, buffering, proxy e frequência de envio.

SSE consegue enviar dados binários?

Não de forma nativa. O formato é texto UTF-8. É possível codificar bytes em texto, mas isso aumenta tamanho e processamento. Para fluxo binário frequente, WebSocket ou outra tecnologia tende a ser mais adequada.

WebSocket é sempre mais rápido que SSE?

Não. WebSocket tem frames compactos e comunicação bidirecional, mas a latência percebida depende do volume, frequência, infraestrutura e processamento. Para atualizações textuais em uma direção, SSE pode atender com menor complexidade.

É possível abrir EventSource com POST?

Não com a interface EventSource nativa, que usa GET. Para iniciar o fluxo com POST e corpo de requisição, use streaming com fetch ou crie o recurso por POST e abra depois uma URL SSE por GET.

SSE e WebSockets podem coexistir no mesmo sistema?

Sim. Um produto pode usar SSE para notificações e progresso, enquanto reserva WebSockets para colaboração ou chat intenso. A escolha pode ser feita por caso de uso, não por aplicação inteira.

Quando polling ainda é suficiente?

Polling é suficiente quando atualizações são pouco frequentes, alguns segundos de atraso são aceitáveis e a simplicidade vale mais que manter conexões abertas.

Ele também serve como linha de base para medir se tempo real acrescenta valor.

Conclusão

A escolha entre SSE vs. WebSockets começa pela direção da conversa. SSE entrega eventos textuais do servidor para o cliente usando uma resposta HTTP persistente, com reconexão nativa e semântica de último evento.

WebSocket mantém um canal bidirecional para mensagens de texto ou binárias, mas exige que a aplicação defina reconexão, retomada e protocolo.

Não use WebSocket apenas porque o produto “tem tempo real”. Para notificações, progresso, feeds e muitos streamings de texto, SSE costuma ser suficiente.

Use WebSocket quando ambos os lados realmente enviam eventos frequentes.

Em qualquer escolha, teste quedas, proxies, clientes lentos, deploys e permissões: são esses detalhes que transformam uma demonstração em um sistema confiável.