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
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
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"}
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);
});
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)