rcRacoelho
HomeBlogDesafiosProjetosSetupVagasComunidade
rcRacoelho

Conteúdo sobre desenvolvimento, tecnologia e desafios de programação para impulsionar sua carreira em tech.

Links rápidos
  • Blog
  • Desafios
  • Projetos
  • Setup
  • Vagas
  • Comunidade
  • Links
Conecte-se
    © 2024–2026 Racoelho. Todos os direitos reservados.v3.0.27 · build 2026-10-04
    rcRacoelho
    HomeBlogDesafiosProjetosSetupVagasComunidade
    blog / Web Development / real-time-polling-sse-ou-websocket
    Web Development

    Real-time: Polling, SSE ou WebSocket?

    Rafael Coelho
    02 mar 2026 · 9 min de leitura

    Tem uma frase que define quase todo bug de “tempo real” na web:

    Você acha que precisa de WebSocket.
    Na verdade, você só precisa parar de fazer polling errado.

    A web nasceu em cima de um acordo simples: eu (cliente) pergunto, você (servidor) responde, a conexão morre.
    Isso funciona tão bem que virou o padrão mental de todo dev.

    Só que “tempo real” é o exato oposto disso.

    Tempo real é o servidor falando sozinho.

    É o sistema te cutucando quando alguma coisa aconteceu: nova mensagem, notificação, mudança de status, nova linha de log, atualização de dashboard.

    A pergunta não é “qual é mais poderoso?”.
    A pergunta certa é: qual é o tipo de conversa que seu app precisa ter?

    Porque as três soluções existem por um motivo: cada uma resolve um “tipo de conversa” diferente.


    O que muda quando você sai do HTTP normal

    No HTTP clássico, você trabalha com “momentos”:

    • eu faço uma request
    • eu recebo uma response
    • acabou

    Em tempo real, você trabalha com “estado contínuo”:

    • eu estou conectado
    • eu continuo recebendo eventos
    • a conexão cai e volta
    • eu não posso perder mensagens importantes
    • eu não posso derrubar meu servidor com 20 mil conexões

    Isso traz três dores práticas que quase ninguém pensa no início:

    A primeira: latência percebida.
    Não é “quanto tempo a requisição leva”. É “quanto tempo o usuário acha que levou pra acontecer”.

    A segunda: custo invisível.
    Não é só CPU e RAM. É conexões abertas, timeouts, proxies no caminho, balanceadores que encerram stream, e limite de conexões simultâneas.

    A terceira: semântica de evento.
    “Notificação” é evento? É estado? Precisa garantir entrega? Pode perder? Pode duplicar?

    A escolha entre Polling / SSE / WebSocket é, na prática, uma escolha entre esses custos e essas semânticas.


    Polling: o martelo que resolve muita coisa (e quebra o resto)

    Vamos desenhar o polling do jeito que ele realmente é.

    Imagine um porteiro de prédio.

    Você quer saber se chegou encomenda.


    Você vai a cada 2 segundos na portaria e pergunta:

    “Chegou algo?”
    “Não.”
    “E agora?”
    “Não.”
    “E agora?”
    “Não.”
    “Chegou algo?”
    “Sim.”

    Esse é o polling.

    O polling “inocente” (e o mais comum)

    js
    setInterval(async () => { const res = await fetch('/api/status'); const data = await res.json(); render(data); }, 2000);

    Funciona em qualquer lugar.
    É por isso que ele nunca morre.

    O problema é que a simplicidade é uma armadilha: você não vê o custo até escalar.

    O custo real aparece quando você multiplica

    Vamos colocar números.

    10.000 usuários online.
    Polling a cada 2 segundos.

    Você acabou de criar 5.000 requests por segundo… mesmo quando nada acontece.

    E pior: cada request carrega header, autenticação, roteamento, middleware, logging, rate limit, etc.
    O custo não é só “uma query no banco”.

    Polling escala mal porque ele gasta recurso quando não tem evento.
    E na vida real, a maior parte do tempo… não tem evento.

    O polling que dói menos (e que muita gente ignora)

    Tem dois upgrades que tornam polling aceitável por mais tempo:

    1) Backoff (aumentar intervalo quando não tem mudança)

    Você começa rápido, e vai desacelerando quando nada acontece.

    2) Long polling (segurar a request no servidor)

    Você faz uma request… e o servidor só responde quando houver algo para responder (ou quando der timeout).

    O long polling já começa a virar “quase SSE”, mas sem o formato de stream.

    Isso aqui muda o jogo, porque reduz o número de requests vazias.

    Quando polling é a escolha certa

    Quando o dado muda pouco, polling é honesto e eficiente.

    Deploy status a cada 30s.
    Relatório que atualiza a cada 1 minuto.
    Fila de processamento que não precisa ser instantânea.

    Polling não é “errado”.
    Ele só não pode fingir que é tempo real de alta frequência.


    SSE: o streaming “puro HTTP” que resolve mais do que deveria

    Agora vamos imaginar outra cena.

    Ao invés de você ir na portaria de 2 em 2 segundos, você fala pro porteiro:

    “Quando chegar encomenda, me chama.”

    Você fica com o telefone ligado.
    O porteiro te liga quando tiver novidade.

    Isso é SSE.

    Você abre um HTTP e deixa aberto.
    O servidor vai empurrando eventos.

    No browser, parece simples demais

    js
    const es = new EventSource('/api/events'); es.onmessage = (event) => { const data = JSON.parse(event.data); render(data); };

    A parte importante não é a API bonitinha.
    É o que isso significa:

    Você não está fazendo milhares de requests por minuto.
    Você está mantendo uma conexão e recebendo eventos quando existem eventos.

    Por que SSE é tão bom no mundo real

    Porque ele é “real-time o suficiente” com infraestrutura “HTTP padrão”.

    Ele atravessa proxy e load balancer com muito menos drama do que WebSocket na maioria dos setups.
    E o navegador já cuida de reconexão automaticamente.

    Ou seja: você ganha “tempo real” sem ganhar “inferno operacional”.

    O que a maioria ignora: SSE é evento, não estado

    SSE entrega eventos.
    Se você reconectar, você pode perder o que aconteceu no meio.

    Então, em SSE bom de verdade, você sempre combina:

    • um endpoint de “estado atual” (pra montar a tela quando entra)
    • um stream de “eventos” (pra atualizar depois)

    Visualmente, fica assim:

    Você entra na página → pega o estado atual (um GET normal)
    Depois abre SSE → recebe alterações em tempo real

    Isso é muito mais robusto do que “SSE pra tudo”.

    Onde SSE brilha

    Streaming de logs.
    Notificações.
    Dashboards ao vivo.
    Feed de atividade.
    Resposta streaming (tipo ChatGPT).

    Na maioria dos produtos SaaS, SSE resolve 80% do “tempo real” sem WebSocket.


    WebSocket: quando você precisa conversar, não só ouvir

    Agora muda o tipo de conversa.

    No SSE, o servidor fala e você escuta.

    Mas e quando você precisa de ida e volta contínua?

    Chat com “digitando…” não é só evento do servidor.
    É o cliente mandando sinal o tempo todo.

    Jogo multiplayer é troca constante.

    Colaboração estilo Google Docs é uma tempestade de eventos indo e voltando.

    Aí você entra no WebSocket.

    Como isso se comporta na prática

    Você abre uma conexão e mantém um canal bidirecional.

    js
    const ws = new WebSocket('wss://exemplo.com/ws'); ws.onopen = () => ws.send(JSON.stringify({ type: 'join', room: 'x' })); ws.onmessage = (e) => { const msg = JSON.parse(e.data); handle(msg); };

    Até aqui parece “só mais uma API”.

    Só que o preço vem depois.

    O preço real do WebSocket (e por que ele assusta infra)

    Cada usuário vira uma conexão aberta.

    Isso mexe com:

    • limite de conexões simultâneas
    • timeouts em proxies
    • sticky sessions (ou necessidade de pub/sub)
    • reconexão manual e sincronização de estado
    • heartbeat/ping/pong
    • backpressure (cliente lento entupindo sua fila de mensagens)

    E o ponto que mata muita arquitetura iniciante:

    Se você tem 3 instâncias do seu backend e um cliente conectado na instância A…
    como a instância B manda uma mensagem pra ele?

    Resposta: você precisa de um “meio do caminho”.

    Redis Pub/Sub, Kafka, RabbitMQ, NATS… alguma camada pra distribuir evento entre nós.

    WebSocket raramente é “só abrir socket”.
    É um sistema de eventos distribuído disfarçado.

    Quando WebSocket é inevitável

    • chat com presença/digitando/entrega
    • jogos
    • colaboração simultânea (documento, quadro, editor)
    • trading/market data com altíssima frequência
    • qualquer cenário onde o cliente também é produtor constante de eventos

    O jeito honesto de escolher: pense no tipo de conversa

    Em vez de matriz bonitinha, pensa assim:

    Se o usuário só precisa “ser avisado”, você está no mundo SSE.
    Se o usuário precisa “conversar em tempo real”, você está no mundo WebSocket.
    Se a mudança é rara e tolera atraso, polling resolve e você dorme em paz.

    Agora, vamos colocar isso em cenas, porque fica mais visual.

    Cena 1: “Seu deploy terminou”

    Você quer ver quando terminou, mas não precisa atualizar 30 vezes por segundo.
    E você não precisa mandar nada pro servidor o tempo todo.

    SSE é perfeito.
    Polling a cada 10–30s também funciona, se você estiver com preguiça.

    Cena 2: “Dashboard de vendas ao vivo”

    Você quer ver números atualizando quando vendas entram.
    Servidor empurra evento. Cliente só atualiza UI.

    SSE.

    Cena 3: “Chat com digitando…”

    Aqui o cliente manda “estou digitando” e recebe “fulano está digitando” o tempo todo.

    WebSocket.

    Cena 4: “Feed de atividades”

    Servidor te manda eventos. Você não precisa mandar nada.

    SSE.

    Cena 5: “Google Docs”

    Você está enviando mudanças pequenas o tempo inteiro e recebendo mudanças de outras pessoas.

    WebSocket + um monte de engenharia extra (CRDT/OT, etc).


    O detalhe que decide tudo: escala e infraestrutura

    Aqui é onde dev bom se separa de dev empolgado.

    Porque “tempo real” não morre no código.
    Ele morre no load balancer.

    Coisas que derrubam real-time na prática

    • Proxy encerrando conexão idle
    • CDN cacheando errado endpoint de evento
    • Serverless matando conexão longa
    • Logs e middleware rodando como se fosse request normal
    • Falta de limite de conexões por instância
    • Falta de mecanismo de fanout (pub/sub)

    Por isso SSE costuma ser o meio-termo mais saudável:
    menos fricção infra que WS, e mais eficiência que polling.


    Código “pronto pra usar” (sem virar tutorial chato)

    Polling com backoff (menos agressivo)

    js
    let delay = 2000; async function poll() { try { const res = await fetch('/api/status'); const data = await res.json(); render(data); // se mudou algo, acelera; se não, desacelera delay = data.changed ? 2000 : Math.min(delay * 1.5, 30000); } catch { delay = Math.min(delay * 2, 60000); } setTimeout(poll, delay); } poll();

    Isso aqui sozinho já elimina a maioria dos “polling é ruim”.


    SSE com estado inicial + stream (robusto)

    js
    async function start() { const snapshot = await fetch('/api/snapshot').then(r => r.json()); render(snapshot); const es = new EventSource('/api/events'); es.onmessage = (e) => { const event = JSON.parse(e.data); applyEvent(event); // atualiza incremental }; } start();

    O truque é: snapshot monta tela, stream mantém viva.


    WebSocket com reconexão simples

    js
    function connect() { const ws = new WebSocket('wss://exemplo.com/ws'); ws.onopen = () => { ws.send(JSON.stringify({ type: 'subscribe', channel: 'chat' })); }; ws.onmessage = (e) => handle(JSON.parse(e.data)); ws.onclose = () => { setTimeout(connect, 1000); }; } connect();

    Esse é o mínimo pra não depender de sorte.


    Fechando: “mais poderoso” quase nunca é “melhor”

    Polling é feio, mas resolve.
    SSE é subestimado e elegante.
    WebSocket é canhão — e canhão exige artilharia (infra, escala, observabilidade).

    Se você quiser uma regra curta pra lembrar:

    Se você só precisa empurrar updates: SSE.
    Se você precisa de conversa contínua: WebSocket.
    Se a atualização é rara e tolera atraso: polling bem feito.

    E o resto é o que sempre foi: contexto, custo e adequação.

    Neste artigo
    • O que muda quando você sai do HTTP normal
    • Polling: o martelo que resolve muita coisa
    • SSE: o streaming “puro HTTP” que resolve mais do que deveria
    • WebSocket: quando você precisa conversar, não só ouvir
    • O jeito honesto de escolher: pense no tipo de conversa
    • O detalhe que decide tudo: escala e infraestrutura
    • Código “pronto pra usar”
    • Fechando: “mais poderoso” quase nunca é “melhor”

    Leia tambémContinue lendo

    8 min

    Você realmente sabe como o JWT funciona? (Ou só acha que sabe?)

    Backend
    6 min

    Dá pra fazer fila sem RabbitMQ? | Protokol

    postgres
    9 min

    O difícil de WebSocket não é mandar mensagem

    rcRacoelho

    Conteúdo sobre desenvolvimento, tecnologia e desafios de programação para impulsionar sua carreira em tech.

    Links rápidos
    • Blog
    • Desafios
    • Projetos
    • Setup
    • Vagas
    • Comunidade
    • Links
    Conecte-se
      © 2024–2026 Racoelho. Todos os direitos reservados.v3.0.27 · build 2026-10-04