Tempo real na web: WebSockets, SSE e quando cada um faz sentido
A web nasceu num modelo simples: o navegador pergunta, o servidor responde, a conexão fecha. Esse ciclo de requisição e resposta funciona perfeitamente para carregar uma página, mas trava diante de uma necessidade cada vez mais comum: o servidor precisa avisar o cliente de que algo mudou, sem que o cliente pergunte. Um chat, uma notificação, um preço que oscila, o cursor de um colaborador em um documento. Nada disso encaixa bem no modelo tradicional, em que o cliente teria que ficar perguntando "mudou?" o tempo todo.
Este guia percorre as tecnologias que trazem o tempo real para a web, do velho long polling aos WebSockets e ao Server-Sent Events, e mostra como escolher entre elas por caso de uso. Também trata da parte que costuma pegar os times de surpresa: escalar conexões persistentes sem derrubar o servidor.
O problema do tempo real
No modelo HTTP clássico, a informação só flui quando o cliente inicia. Para simular atualização em tempo real, a saída ingênua é o cliente perguntar de novo e de novo. O desafio de qualquer solução de tempo real é entregar o dado novo assim que ele existe, com baixa latência e sem desperdiçar recursos com perguntas vazias. Há três abordagens principais, com graus diferentes de sofisticação.
Long polling: o truque antigo
O long polling é a forma mais simples de emular tempo real sobre HTTP comum. O cliente faz uma requisição, e o servidor segura a resposta em aberto até ter algo novo para enviar. Quando envia, o cliente imediatamente abre outra requisição, e o ciclo recomeça.
Funciona em qualquer lugar, porque é só HTTP, e por isso ainda serve como fallback. Mas é ineficiente: cada mensagem carrega o custo de uma requisição HTTP completa (cabeçalhos, handshake), e manter muitas conexões seguradas pressiona o servidor. Long polling é a solução de compatibilidade, não a de primeira escolha quando você tem alternativas melhores.
WebSockets: a via de mão dupla
O WebSocket abre um canal bidirecional e persistente entre cliente e servidor sobre uma única conexão TCP. Depois de um handshake inicial (que começa como HTTP e faz upgrade para o protocolo WebSocket), os dois lados podem enviar mensagens a qualquer momento, sem o custo de reabrir conexões.
É a tecnologia certa quando os dois lados falam com frequência:
- Chat e mensageria, em que cliente e servidor trocam mensagens o tempo todo.
- Colaboração ao vivo, como edição simultânea de documentos e quadros.
- Jogos e interações de baixa latência, em que cada milissegundo conta.
- Dashboards interativos que enviam comandos e recebem atualizações.
O poder tem custo: WebSocket é um protocolo diferente do HTTP, o que exige suporte na infraestrutura (balanceadores, proxies) e uma estratégia própria de autenticação, reconexão e escala. Você adota WebSocket quando precisa de verdade da via de mão dupla, não por ser o mais moderno.
Server-Sent Events: o fluxo de mão única
Nem todo caso de tempo real precisa que o cliente fale de volta pelo mesmo canal. Muitas vezes o cliente só quer receber um fluxo de atualizações. Para isso existe o Server-Sent Events (SSE): um canal unidirecional, do servidor para o cliente, sobre uma conexão HTTP comum mantida aberta.
O SSE é subestimado. Ele é mais simples que o WebSocket, roda sobre HTTP puro (então atravessa proxies e balanceadores sem drama), e traz de fábrica reconexão automática e numeração de eventos para retomar de onde parou. É ideal para:
- Notificações e alertas empurrados pelo servidor.
- Feeds de atualização, como cotações, placares e status de um processo.
- Streaming de progresso, incluindo respostas de modelos de IA token a token.
A limitação é a direção única: se o cliente precisa mandar dados de volta com frequência, ele faz isso por requisições HTTP normais, em paralelo. Se a conversa é majoritariamente de mão única, do servidor para o cliente, o SSE entrega quase tudo que o WebSocket entregaria, com uma fração da complexidade.
Comparando as três abordagens
| Critério | Long polling | WebSockets | SSE |
|---|---|---|---|
| Direção | Cliente pede, servidor responde | Bidirecional | Servidor para cliente |
| Protocolo | HTTP | WebSocket (upgrade) | HTTP |
| Eficiência | Baixa | Alta | Alta |
| Reconexão automática | Manual | Manual | Nativa |
| Complexidade de infra | Baixa | Alta | Baixa |
| Melhor para | Fallback universal | Chat, colaboração, jogos | Notificações, feeds, streaming |
A leitura prática: comece perguntando a comunicação é de mão dupla?. Se não, o SSE quase sempre vence pela simplicidade. Se sim, e com alta frequência nos dois sentidos, o WebSocket se justifica. Long polling fica como rede de segurança para ambientes que não suportam os outros dois.
O verdadeiro desafio: escalar conexões persistentes
Aqui está o que os tutoriais raramente contam. Abrir uma conexão de tempo real é fácil com dez usuários. Com cem mil conexões simultâneas, surgem problemas que não existem no HTTP tradicional, porque agora o servidor mantém estado aberto para cada cliente.
Sticky sessions e o problema do estado
No HTTP sem estado, qualquer servidor atende qualquer requisição. Com conexões persistentes, o cliente fica preso a um servidor específico, aquele onde sua conexão vive. Isso exige sticky sessions (afinidade de sessão) no balanceador, para que o tráfego daquele cliente volte sempre ao mesmo nó. Introduz rigidez: se aquele nó cai, todas as suas conexões caem junto e precisam reconectar.
Pub/sub para distribuir mensagens entre nós
O problema maior aparece com múltiplos servidores. O usuário A está conectado ao servidor 1; o usuário B, ao servidor 2. Quando A envia uma mensagem para B, o servidor 1 não tem como falar diretamente com a conexão de B, que vive no servidor 2. A solução padrão é um backplane de pub/sub (por exemplo, um Redis no papel de publicador e assinante): o servidor 1 publica a mensagem em um canal, e o servidor 2, inscrito nesse canal, a entrega a B. Assim, qualquer nó alcança qualquer conexão, independentemente de onde ela esteja.
Heartbeats e reconexão
Conexões persistentes morrem silenciosamente: um proxy no meio pode fechar uma conexão ociosa sem avisar nenhum dos lados. Por isso, sistemas de tempo real usam heartbeats (pings periódicos) para detectar conexões mortas e liberar recursos, e o cliente precisa de uma estratégia de reconexão com backoff, para voltar sozinho quando a conexão cai. O SSE já traz reconexão de fábrica; com WebSocket, você a implementa.
Escolhendo sem exagerar
Tempo real encanta, e o excesso é uma armadilha. Nem toda tela precisa de conexão persistente: às vezes um refresh a cada trinta segundos resolve, com uma fração do custo. Um roteiro sóbrio:
- A atualização pode esperar alguns segundos e é pouco frequente? Polling simples pode bastar, sem conexão persistente.
- O servidor empurra, o cliente só recebe? SSE, pela simplicidade e reconexão nativa.
- Os dois lados conversam muito, com baixa latência? WebSocket, assumindo o custo de infra.
- Precisa funcionar em qualquer ambiente hostil a conexões modernas? Mantenha long polling como fallback.
A pergunta certa nunca é "qual a tecnologia de tempo real mais avançada?", e sim "qual o menor grau de tempo real que a minha experiência exige?". Conexões persistentes trazem estado, afinidade e um backplane para operar. Vale a pena quando a experiência pede; é peso morto quando não pede.
Seu produto precisa de tempo real e você não sabe como escalar isso? Na ConstructorTI, desenhamos camadas de tempo real com a tecnologia certa para cada caso, de SSE enxuto a WebSockets com pub/sub e reconexão resiliente, sem transformar a arquitetura em um problema de estado distribuído. Se você quer chat, notificações ou colaboração ao vivo que aguentem escala, fale com a nossa engenharia e receba um diagnóstico da sua camada de tempo real.