Tempo real (WebSocket e SSE)
Formas de o servidor enviar dados ao cliente sem esperar um pedido, e o custo de manter conexões abertas.
O problema: o HTTP só responde quando perguntam
No HTTP, o cliente pergunta e o servidor responde. O servidor nunca toma a iniciativa. Isso é um problema quando a informação nasce no servidor e o cliente precisa saber logo:
- o status do pedido mudou para "saiu para entrega";
- chegou uma mensagem nova no chat;
- a exportação de relatório terminou;
- o preço de um item mudou.
Há três formas principais de resolver, cada uma com um custo diferente.
Consultas periódicas
O cliente pergunta de tempos em tempos: "o status mudou?".
cliente: GET /pedidos/981 → servidor: "aberto"
(espera 5 segundos)
cliente: GET /pedidos/981 → servidor: "aberto"
(espera 5 segundos)
cliente: GET /pedidos/981 → servidor: "pago"| Vantagens | Custos |
|---|---|
| Funciona com qualquer cliente, proxy e infraestrutura | A maioria das consultas volta sem novidade |
| Nenhuma conexão fica aberta | A novidade chega com atraso de até um intervalo inteiro |
| Simples de implementar e de escalar | Com milhares de clientes, gera milhares de pedidos por segundo à toa |
Com intervalo de 5 segundos e 10 mil clientes com a tela aberta, são 2 mil pedidos por segundo, quase todos para responder "nada mudou". Para muitas telas, isso é aceitável. Para atualizações frequentes ou muitos clientes, não.
Uma variação, a consulta longa (long polling), deixa o pedido aberto até haver novidade ou passar um tempo limite, e o cliente pergunta de novo logo em seguida. Reduz o atraso, mas mantém conexões abertas e é mais difícil de acertar que as alternativas abaixo.
Server-Sent Events (SSE)
O cliente abre um pedido HTTP comum, e o servidor deixa a resposta aberta, escrevendo eventos à medida que eles acontecem:
GET /eventos HTTP/1.1
Accept: text/event-streamHTTP/1.1 200 OK
Content-Type: text/event-stream
id: 1
event: progresso
data: {"pedido":981,"etapa":1}
id: 2
event: progresso
data: {"pedido":981,"etapa":2}
: pingO formato é texto simples: cada evento tem um identificador (id), um tipo (event) e os dados (data), separados por uma linha em branco. Linhas começando com : são comentários, usados como pulso para manter a conexão viva.
No navegador, a API EventSource cuida de tudo, inclusive da parte mais valiosa: a reconexão automática. Se a conexão cair, o navegador reconecta sozinho e envia o cabeçalho Last-Event-ID com o último evento recebido. O servidor continua de onde parou.
Testamos num Chrome real: o servidor foi derrubado depois do evento 5 e religado 1,5 segundo depois. O navegador reconectou sozinho, enviou Last-Event-ID: 5, e recebeu os eventos de 6 a 11. Nenhum evento repetido, nenhum perdido, e nenhuma linha de código de reconexão no cliente.
| Vantagens | Limites |
|---|---|
| HTTP comum: funciona com proxies, balanceadores, autenticação e ferramentas existentes | Só o servidor envia; o cliente usa pedidos HTTP normais para falar com o servidor |
| Reconexão e retomada embutidas no navegador | Só texto; dados binários precisam ser codificados |
| Simples de implementar em qualquer linguagem | No HTTP/1.1, os navegadores limitam a seis conexões por domínio, somando todas as abas |
WebSocket
O WebSocket começa como um pedido HTTP e o converte num canal bidirecional permanente:
GET /chat HTTP/1.1
Upgrade: websocket
Connection: UpgradeHTTP/1.1 101 Switching ProtocolsA partir daí, cliente e servidor trocam mensagens nos dois sentidos, a qualquer momento, sem cabeçalhos HTTP a cada mensagem.
| Vantagens | Custos |
|---|---|
| Canal nos dois sentidos, com pouca sobrecarga por mensagem | Não é mais HTTP depois da abertura: cada proxy, balanceador e firewall precisa suportar |
| Aceita dados binários | Reconexão, retomada e pulsos ficam por conta da aplicação |
| Latência mínima | Autenticação, limites e observação precisam de tratamento próprio |
Quando cada um
| Necessidade | Forma |
|---|---|
| Atualizações raras, poucos clientes | Consultas periódicas |
| Notificações, status, progresso, painéis | SSE |
| Chat, edição colaborativa, jogos: o cliente também envia muito, com baixa latência | WebSocket |
A maioria dos casos de "tempo real" em sistemas de negócio é de mão única: o servidor avisa, e o cliente reage com pedidos comuns. Para esses, o SSE resolve com menos infraestrutura que o WebSocket.
O que pode atrapalhar no caminho
Conexões que ficam abertas por minutos ou horas encontram obstáculos que um pedido comum não encontra:
| Obstáculo | O que acontece | Defesa |
|---|---|---|
| Compressão no proxy | O proxy acumula a resposta para comprimir, e os eventos ficam presos | Cabeçalho X-Accel-Buffering: no (Nginx) ou desligar a compressão para text/event-stream |
| Tempo limite de ociosidade | Balanceadores e proxies fecham conexões sem tráfego depois de algum tempo (60 segundos no Nginx, por padrão) | Pulsos periódicos (: ping no SSE, ping no WebSocket) |
| Conexões mortas sem aviso | O cliente sumiu (celular sem sinal), mas o servidor só descobre ao tentar escrever | Pulsos, e encerrar quem não responde |
O primeiro obstáculo foi testado com um Nginx na frente de um servidor SSE. Com a configuração padrão do Nginx, os eventos chegaram normalmente: 9 em 3 segundos. Com a compressão ligada para text/event-stream, o cliente recebeu 0 eventos em 3 segundos, presos no proxy. Com o cabeçalho X-Accel-Buffering: no enviado pela aplicação, os 9 voltaram a chegar mesmo com a compressão ligada.
Por que isso importa quando a IA escreve o código
Um assistente que implementa "atualização em tempo real" costuma escolher o mais conhecido e o mais simples de testar:
- WebSocket para um caso de mão única, que o SSE resolveria com menos infraestrutura.
- Nenhum pulso, e conexões fechadas pelo balanceador depois de um minuto parado.
- Nenhuma retomada: o cliente que reconecta perde os eventos do intervalo.
- O evento publicado só para os clientes da instância atual.
- Compressão ou buffer no caminho, segurando os eventos sem ninguém entender por quê.
O próximo nível compara as formas em detalhe, inclusive a escala com milhares de conexões abertas.
Prompts para aprofundar
Ao abrir no ChatGPT ou no Claude, o prompt é enviado ao serviço escolhido pela URL e também fica copiado na sua área de transferência.
Tempo real em cinco minutos
Explique em no máximo cinco minutos de leitura como um servidor pode avisar o cliente de algo que aconteceu, para alguém que só conhece o modelo de pedido e resposta do HTTP. Cubra só o essencial: consultas periódicas, Server-Sent Events e WebSocket, o que cada um faz e quando usar cada um. Use o exemplo de acompanhar o status de um pedido. No final, me faça três perguntas curtas para eu verificar se entendi, e corrija as minhas respostas.
Consultas, SSE e WebSocket por dentro
Quero entender como funcionam as três formas de comunicação em tempo real. Aja como um mentor. Para cada forma, uma de cada vez: 1. Mostre o que trafega na rede: os pedidos, os cabeçalhos e as mensagens. 2. Explique quantas conexões ficam abertas e por quanto tempo. 3. Explique o que acontece quando a conexão cai. 4. Peça que eu calcule o custo para 10 mil clientes com a tela aberta. No final, monte comigo uma tabela comparando direção, atraso, reconexão, compatibilidade com proxies e complexidade.
Por que o SSE é subestimado
Quero entender o Server-Sent Events em detalhe. Explique: 1. O formato do fluxo: id, event, data, retry e comentários. 2. Como o EventSource do navegador reconecta sozinho e o papel do cabeçalho Last-Event-ID. 3. Por que o SSE funciona com a infraestrutura HTTP existente, e quais cuidados ele ainda exige (compressão, buffer, tempo de ociosidade). 4. As limitações: só texto, só do servidor ao cliente, limite de conexões por domínio no HTTP/1.1. 5. Por que muitos casos que usam WebSocket seriam resolvidos com SSE. Depois me descreva cinco funcionalidades e pergunte se eu usaria SSE, WebSocket ou consultas. Corrija as minhas respostas.
O que atrapalha conexões longas
Quero entender os problemas que conexões longas encontram em produção. Explique, com um exemplo para cada um: 1. Proxies que acumulam a resposta ou a comprimem, segurando os eventos. 2. Tempos limite de ociosidade em balanceadores e proxies. 3. Conexões mortas sem aviso, como um celular que perdeu o sinal. 4. Várias instâncias da aplicação, com o evento nascendo numa e o cliente conectado em outra. 5. Deploys que derrubam milhares de conexões de uma vez. Para cada um, diga a defesa e como testar.