en
· 4 min de leitura

WebSockets, SSE ou polling: uma tabela de decisão

Três jeitos de levar dado ao vivo ao navegador. O certo depende de direção, escala e hospedagem, não do que soa moderno.

fullstacksystem-design

Todo produto uma hora precisa que algo na tela atualize sem refresh. Um contador de notificações, um status de pedido, uma mensagem de chat, um número de dashboard. Nesse momento alguém diz WebSockets, porque é a resposta que ouviu falar, e o time herda uma camada de conexões persistentes de que não precisava.

Existem três opções honestas, e a certa sai de quatro perguntas: em que direção o dado flui, com que frequência muda, quantos clientes estão conectados e o que a sua hospedagem consegue manter vivo.

As três opções, sem rodeio

Polling é o cliente perguntando num timer. É sem estado, funciona através de todo proxy e cache que existe, e custa uma requisição por cliente por intervalo, tenha algo mudado ou não. Com intervalo de quinze segundos e dez mil clientes, são quarenta mil requisições por minuto para dados que mudam duas vezes por hora.

Server-Sent Events é uma única resposta HTTP de longa duração na qual o servidor escreve sempre que há algo novo. Flui em um sentido, do servidor para o cliente. O navegador reconecta automaticamente e envia o id do último evento que viu, para o servidor retomar de onde parou. Multiplexa bem sobre HTTP/2 e é texto puro sobre HTTP puro, o que significa que load balancers e CDNs entendem. No Next.js um route handler pode retornar um readable stream e funciona, desde que o deploy não corte respostas longas.

WebSockets é um socket full-duplex promovido a partir do HTTP. Os dois lados enviam a qualquer momento, com pouco overhead por mensagem. É a única opção quando o cliente precisa enviar com frequência, como edição colaborativa ou um jogo. Também é uma conexão com estado que uma função serverless não consegue segurar, então precisa de um processo de longa duração ou de um serviço gerenciado, e esse é o custo que as pessoas esquecem.

A tabela de decisão

  • Dado muda raramente e frescor dentro de um minuto basta: polling, com intervalo sensato e header de cache para o CDN absorver a carga.
  • Servidor empurra atualizações e o cliente só lê: SSE. Notificações, barras de progresso, feeds de status, saída de modelo em streaming.
  • Os dois lados enviam com frequência, latência importa, taxa de mensagens é alta: WebSockets, em infraestrutura que consegue manter conexões.
  • Hospedagem serverless sem processo persistente: SSE se a plataforma permite respostas longas, senão polling. WebSockets precisam de um serviço separado.
  • Dezenas de milhares de clientes simultâneos: seja qual for a escolha, a contagem de conexões é o limite de capacidade, e uma camada de pub/sub atrás é obrigatória.

Os modos de falha

Polling falha por custo e por manada. Todo cliente que carregou a página no mesmo minuto consulta no mesmo segundo. Adicione jitter ao intervalo e reduza a frequência quando a aba está oculta.

SSE falha por proxies que fazem buffer. Um reverse proxy configurado para bufferizar respostas segura o stream até encher um buffer, e o cliente não vê nada por um minuto e depois vê tudo de uma vez. Desabilite o buffer para a rota de streaming, envie um comentário de heartbeat a cada quinze a trinta segundos para conexões ociosas não serem fechadas, e tenha em mente a contagem de conexões por processo, porque cada uma é um arquivo aberto.

WebSockets falham por estado. Uma conexão vive em um servidor. Quando você tem dois servidores, uma mensagem publicada no primeiro precisa chegar aos clientes presos ao segundo, o que significa um broker entre eles. Quando um servidor reinicia, todos os clientes reconectam de uma vez, e se a reconexão não tem backoff, o restart vira uma queda. E a conexão sobrevive à sessão: o usuário desloga, o socket continua aberto e autorizado até você fechá-lo de propósito.

O que eu costumo escolher

Para a maioria dos produtos, SSE para atualizações do servidor ao cliente e requisições HTTP comuns para ações do cliente ao servidor cobre tudo. O cliente envia a mutação do jeito normal, por uma Server Action ou uma rota, o servidor grava o resultado e publica um evento, e o evento desce pelo stream. Dois mecanismos simples, sem estado duplex, e roda na infraestrutura que você já tem.

WebSockets merecem o lugar deles na faixa estreita em que o cliente é uma mangueira de incêndio. Em todo o resto, são uma conexão persistente que você paga para manter viva para que ela carregue uma notificação por hora.