DEV Community

Marcus Dorbação
Marcus Dorbação

Posted on

SSE (Server-Sent Events): como funciona por baixo dos panos

Se você já precisou que um servidor "avisasse" o navegador quando algo mudasse — sem ficar dando refresh ou fazendo polling a cada X segundos — provavelmente esbarrou em duas opções: WebSocket ou SSE (Server-Sent Events). Este artigo foca no segundo: o que é, e como ele funciona tecnicamente.

O que é

SSE é um mecanismo de comunicação unidirecional (servidor → cliente), construído sobre HTTP comum. O servidor mantém uma única conexão aberta e vai empurrando eventos de texto para o cliente conforme eles acontecem, sem que o cliente precise ficar perguntando "tem novidade?".

Diferente do WebSocket, não existe handshake especial nem troca de protocolo — é uma requisição HTTP GET normal, que simplesmente nunca termina.

O fluxo, passo a passo

1. O cliente abre a conexão

GET /stream HTTP/1.1
Host: api.exemplo.com
Accept: text/event-stream
Enter fullscreen mode Exit fullscreen mode

Uma requisição GET comum — nada de upgrade de protocolo.

2. O servidor responde e não fecha a conexão

HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
Enter fullscreen mode Exit fullscreen mode

O Content-Type: text/event-stream avisa o cliente: "isso é um stream contínuo, não espere o corpo terminar".

3. O servidor envia eventos como texto

Cada evento é um bloco separado por linha em branco:

event: flag-update
data: {"flagKey": "novo-checkout", "value": true}

data: heartbeat

event: flag-update
data: {"flagKey": "cancelar-nota", "value": "variante-b"}

Enter fullscreen mode Exit fullscreen mode

Campos possíveis:

Campo Para que serve
data: O payload do evento (pode ter várias linhas)
event: Nome do tipo de evento — permite o cliente ter listeners diferentes por tipo
id: Identificador do evento, usado para retomar de onde parou após reconexão
retry: Tempo em ms que o cliente deve esperar antes de tentar reconectar

4. O cliente processa cada evento

No navegador, isso é nativo via EventSource:

const source = new EventSource('/stream');

source.addEventListener('flag-update', (e) => {
  const data = JSON.parse(e.data);
  console.log('Atualização recebida:', data);
});
Enter fullscreen mode Exit fullscreen mode

5. Se a conexão cair, reconecta sozinho

Esse é um dos pontos mais úteis do SSE: o EventSource reconecta automaticamente, sem precisar de código extra — e reenvia o header Last-Event-ID com o último id: recebido, permitindo o servidor retomar exatamente de onde parou, em vez de reenviar tudo desde o início.

Características técnicas que valem lembrar

  • Só texto: o payload é sempre string, geralmente JSON serializado — não dá para mandar binário direto
  • Unidirecional: o cliente não consegue mandar dados de volta pela mesma conexão. Se precisar de um "ack" ou enviar algo, é uma requisição HTTP separada
  • Roda sobre infraestrutura HTTP comum: proxies, load balancers e CDNs já sabem lidar com isso, diferente do WebSocket, que às vezes exige suporte especial nesses componentes
  • Limite de conexões no HTTP/1.1: navegadores limitam a ~6 conexões simultâneas por domínio; isso deixa de ser um problema no HTTP/2, que multiplexa várias streams numa única conexão TCP

Quando faz sentido usar

SSE é a escolha certa quando o fluxo de dados é só do servidor para o cliente — notificações, atualizações de status, feeds em tempo real, mudanças de configuração. Se o cliente também precisa mandar dados pela mesma conexão em tempo real (ex: um chat, um jogo multiplayer), WebSocket é o caminho, porque ali a comunicação é bidirecional.

Top comments (0)