Introdução
Tempo real no Angular e .NET parece simples até o momento em que a equipe precisa escolher a tecnologia certa para sair do “funciona na minha máquina” e chegar em produção sem fragilidade. Em geral, a discussão começa com um pedido vago do produto: “precisamos que a tela atualize sozinha”. A partir daí aparecem quatro caminhos muito diferentes: WebSockets, Server-Sent Events (SSE), SignalR e Long Polling. Eles não são equivalentes, não resolvem o mesmo cenário com o mesmo custo e não devem ser tratados como sinônimos.
Eu escrevi este tutorial para responder a pergunta que realmente importa: quando usar cada abordagem sem superengenharia. Em alguns casos, um stream unidirecional já resolve. Em outros, a aplicação precisa de canal bidirecional, fallback automático e uma abstração que esconda a complexidade do protocolo. E, em certos ambientes corporativos, a solução mais feia na teoria vira a mais confiável na prática porque atravessa proxies, balanceadores e políticas de rede com menos atrito.
O ponto central aqui é pragmático. WebSockets oferecem comunicação bidirecional persistente. SSE entrega atualização do servidor para o navegador sobre HTTP com uma API simples. SignalR é uma abstração de alto nível para ASP.NET Core que escolhe o melhor transporte disponível e ainda oferece hubs, grupos e reconexão. Long Polling continua existindo porque compatibilidade e previsibilidade ainda ganham de elegância em ambientes onde WebSockets e SSE são bloqueados.
💡 Dica: quando o requisito é só empurrar eventos do servidor para o cliente, comece por SSE ou SignalR antes de partir para WebSockets. Em muitos produtos, a menor solução suficiente é a que sobrevive melhor ao longo do tempo.
Neste artigo eu também uso o repositório de exemplos do blog como apoio prático. O sample em .NET e Angular foi preparado para mostrar o mesmo fluxo de processamento em quatro transportes diferentes, sem esconder o que muda no frontend, no backend e na operação.
Pré-requisitos
Para acompanhar o tutorial, você vai precisar de:
- .NET 10 SDK para executar o backend do sample
- Node.js ou Bun para rodar o frontend Angular de demonstração
- Conhecimento básico de ASP.NET Core, Angular e HTTP
- Familiaridade com o conceito de endpoint, hub e requisição assíncrona
Clone o repositório de exemplos:
| |
Se você quiser reproduzir o cenário localmente, o backend fica em src/BlogSamples e o frontend de demonstração em frontend/search-ui-bun/. O sample foi pensado para exibir uma tarefa de processamento com evolução incremental, justamente para evidenciar a diferença entre transporte, latência e complexidade de cliente.
⚠️ Atenção: SSE depende de resposta em streaming. Em Nginx, Cloudflare e outros proxies, buffering pode atrasar ou quebrar a experiência se o backend não escrever e flushar os eventos corretamente.
Quando cada tecnologia faz sentido
Antes de entrar na implementação, eu gosto de reduzir a discussão a um critério simples: qual direção o fluxo de dados precisa seguir? Se a aplicação só precisa publicar estados, notificações ou progresso, não há motivo para pagar o custo cognitivo de uma conexão bidirecional completa. Se o cliente também precisa enviar comandos frequentes em tempo real, aí a conversa muda.
O Long Polling é o ponto de partida mais conservador. Ele funciona com qualquer infraestrutura HTTP tradicional, atravessa proxies mais restritivos e é fácil de entender: o cliente faz uma requisição, o servidor segura até haver dado novo ou até o timeout. Em troca, você paga com latência e overhead de conexões repetidas. É um compromisso útil quando compatibilidade vence elegância.
O SSE é um meio-termo muito interessante para dashboards, trilhas de auditoria, status de jobs e feeds de notificação. Ele usa uma conexão HTTP aberta e o navegador recebe eventos continuamente via EventSource. O cliente não envia mensagens pelo mesmo canal, então a solução fica naturalmente unidirecional. Isso reduz a superfície do problema, simplifica a implementação e ainda é mais compatível do que muita equipe imagina.
WebSockets entram quando a conversa precisa ser bidirecional de verdade. Chat, colaboração, jogos, telemetria interativa, edição simultânea e comandos em tempo real são cenários em que o modelo full-duplex faz sentido. O preço é conhecido: conexão persistente, atenção extra com escalabilidade, afinidade em balanceadores e maior sensibilidade a intermediários de rede.
SignalR resolve outra categoria de problema: eu quero um contrato de tempo real em ASP.NET Core sem me obrigar a escolher o transporte manualmente em cada caso. O framework negocia WebSockets, SSE e Long Polling conforme a plataforma permite. Em projetos .NET, isso reduz atrito e ainda oferece recursos de alto nível como hubs, grupos e reconexão.
Em resumo: Long Polling é a rede de segurança, SSE é o stream simples e eficiente, WebSockets é o canal persistente e bidirecional, e SignalR é a abstração que distribui a decisão para o runtime.
WebSockets na prática com .NET e Angular
WebSockets começam como HTTP e depois fazem upgrade para um canal persistente. Esse detalhe muda tudo: a conexão deixa de ser um ciclo de requisição e resposta e passa a ser um tubo aberto para ambos os lados. Isso significa menos overhead por mensagem, baixa latência e um modelo mental muito útil para aplicações que precisam reagir a interações do usuário e eventos do servidor sem reabrir conexão a cada ação.
Na prática, o ganho vem com responsabilidades extras. WebSockets exigem atenção com escalabilidade horizontal, porque a conexão permanece viva e pode depender de afinidade de sessão ou de um backplane para distribuição de mensagens. Também é comum encontrar proxy corporativo, gateway ou CDN que não trata WebSockets tão bem quanto o tráfego HTTP comum. Isso não torna a tecnologia ruim; só obriga a uma análise mais séria do ambiente.
O cenário mais forte para WebSockets em Angular e .NET é quando o cliente também envia comandos frequentes: iniciar uma tarefa, cancelar uma operação, ajustar parâmetros de execução ou manter uma sessão interativa. Em vez de abrir novas requisições para cada passo, o cliente e o servidor compartilham um canal contínuo.
📝 Exemplo: num painel de supervisão de jobs, o usuário pode disparar uma tarefa, receber progresso incremental e cancelar a operação sem sair do mesmo canal de comunicação.
SSE na prática com .NET e Angular
SSE, ou Server-Sent Events, é o oposto do glamour tecnológico e exatamente por isso ele costuma ser tão útil. O browser abre uma conexão HTTP com EventSource e fica escutando eventos nomeados enviados pelo servidor. Não há bidirecionalidade no mesmo canal; o servidor escreve, o cliente lê. Parece limitado, mas para atualização de status, notificações, progresso de processamento e feeds de eventos isso é frequentemente suficiente.
O ponto forte do SSE é a simplicidade operacional. Como ele permanece muito próximo de HTTP, costuma ser mais fácil de atravessar infraestrutura existente do que uma conexão WebSocket. A API no browser é enxuta e a reconexão pode ser tratada com comportamento nativo ou com pequena camada de código. Para aplicações Angular, isso combina bem com uma interface reativa que só precisa refletir o estado mais recente.
O cuidado principal está na entrega do stream. Se o backend escreve o evento mas o proxy segura o buffer, o usuário não vê nada até o flush ou até o buffering ser desativado. É exatamente por isso que SSE precisa ser documentado junto com a arquitetura de borda, e não apenas como um detalhe de controller.
SignalR como camada de abstração
SignalR é onde muita discussão fica confusa, então vale separar bem os papéis. SignalR não é “um protocolo concorrente” de WebSockets. Ele é uma abstração de alto nível para aplicações em ASP.NET Core que escolhe o transporte disponível e entrega uma experiência mais simples para o desenvolvedor. Se WebSockets está disponível, ótimo. Se não estiver, SignalR pode cair para SSE ou Long Polling sem quebrar o contrato do aplicativo.
Para times .NET, isso costuma ser valioso porque reduz decisões repetitivas. Em vez de cada tela decidir sozinha como falar com o backend, eu centralizo a conversa em hubs, métodos e eventos. O frontend chama um método, o hub responde com um evento, e o framework negocia o transporte no meio. Isso também ajuda quando você quer grupos, broadcast seletivo, reconexão automática e um modelo de domínio mais claro.
O trade-off é que essa camada pode esconder detalhes que a equipe deveria entender. SignalR ajuda, mas não elimina a necessidade de saber quando WebSockets, SSE ou Long Polling estão por trás da abstração. Se a aplicação precisa de previsibilidade extrema em um ambiente específico, é melhor medir o comportamento real do que assumir que o framework resolverá tudo sozinho.
Long Polling como fallback e compatibilidade máxima
Long Polling é frequentemente tratado como técnica antiga, mas isso é um erro de leitura. Ele continua sendo importante porque existe uma quantidade enorme de ambientes em que o melhor protocolo é simplesmente o que passa pelo firewall, pelo proxy e pela política de segurança sem discussão. Em vez de abrir um canal persistente, o cliente faz uma requisição e o servidor segura a resposta até haver atualização ou timeout.
O efeito prático é previsibilidade. Você pode pagar com latência maior e mais overhead de requisição, mas ganha compatibilidade quase universal. Para usuários atrás de proxies muito restritivos, ambientes corporativos com regras conservadoras e stacks legadas, Long Polling ainda é uma solução válida. É melhor ter um fallback mais lento do que não ter atualização alguma.
O problema real é tentar usar Long Polling como primeira escolha quando a aplicação claramente pede um canal mais eficiente. Se o produto depende de muitos eventos por segundo ou de interação instantânea, o custo de repetição de requisições rapidamente aparece em CPU, rede e observabilidade. Nessa situação, Long Polling deve ficar na reserva, não no volante.
Matriz de decisão para escolher a abordagem
Quando eu preciso decidir rápido, uso uma matriz simples:

| Cenário | Melhor ponto de partida | Motivo |
|---|---|---|
| Somente servidor → cliente | SSE | Menor complexidade, stream HTTP simples |
| Cliente também envia comandos frequentes | WebSockets | Canal bidirecional real |
| Quero abstração em ASP.NET Core e fallback automático | SignalR | Negociação de transporte e hubs |
| Infraestrutura restritiva ou legado | Long Polling | Maior compatibilidade |
| UI de dashboard com progresso de jobs | SSE ou SignalR | Baixa complexidade e boa UX |
| Chat ou colaboração em tempo real | WebSockets ou SignalR | Bidirecionalidade e latência baixa |
Essa matriz não substitui medições, mas evita a armadilha mais comum: usar a tecnologia mais poderosa só porque ela é mais empolgante. Em produção, o menor mecanismo que cumpre o requisito é frequentemente o que dá menos trabalho para operar.
Exemplo Prático
O sample do blog foi montado para mostrar o mesmo fluxo de tarefa com quatro transportes. No backend, eu exponho um endpoint de criação, um endpoint de consulta e um stream para SSE e WebSocket. No frontend Angular, eu alterno a conexão conforme o transporte escolhido e atualizo a mesma interface com o mesmo modelo de evento.
Backend .NET
| |
📂 Código Fonte: O exemplo completo do backend está disponível no repositório de exemplos do blog em BlogSamples/Messaging/TempoReal/.
Angular com SignalR
| |
📂 Código Fonte: O frontend de demonstração está no repositório de exemplos do blog em frontend/search-ui-bun/, onde eu adaptei a interface para alternar entre os quatro transportes.
O detalhe importante aqui não é a quantidade de linhas, mas o modelo mental. O mesmo backend produz o mesmo estado de tarefa; o que muda é como esse estado cruza a rede e como a interface decide escutar as atualizações.
Dicas e Boas Práticas
Comece pelo requisito de direção de dados. Se o fluxo é apenas servidor → cliente, eu prefiro SSE ou SignalR antes de pensar em WebSockets. Isso reduz complexidade, facilita a operação e evita abrir um canal mais caro do que o necessário.
Desative buffering quando usar SSE. Streaming sem flush de resposta vira “quase streaming”. Em produção, eu sempre valido a cadeia completa de proxy, CDN e servidor para garantir que os eventos chegam ao navegador no tempo esperado.
Trate SignalR como contrato, não como mágica. Ele resolve muita coisa, mas continua dependendo de transporte, reconexão e política de rede. Entender o que acontece por baixo evita surpresas quando o ambiente troca de WebSocket para Long Polling.
Use Long Polling como fallback consciente. Ele é útil quando a infraestrutura é restritiva, mas não é a escolha ideal para alto volume. Se a aplicação cresce, a diferença de custo em requisições e latência aparece rápido.
Modele o estado do evento de forma estável. O cliente não deveria precisar adivinhar o significado de cada payload. Um modelo único de evento simplifica logs, debug, reconexão e renderização na UI.
Observe o ambiente de borda desde o início. Proxies, balanceadores, políticas de segurança e timeouts são parte da arquitetura de tempo real, não detalhes operacionais. Ignorar isso gera um sistema que funciona no dev e falha fora dele.
Resumo Objetivo
- WebSockets — oferecem comunicação bidirecional persistente sobre uma conexão única, o que reduz overhead por mensagem e favorece cenários interativos como chat e colaboração.
- SSE — entregam eventos do servidor para o navegador via
text/event-stream, com API nativa no browser e simplicidade operacional para dashboards e notificações. - SignalR — é uma abstração de alto nível do ASP.NET Core que negocia WebSockets, SSE ou Long Polling e expõe hubs, grupos e reconexão.
- Long Polling — mantém a compatibilidade máxima com infraestrutura HTTP tradicional, mas paga com mais latência e mais requisições ao servidor.
- Angular + .NET — funcionam muito bem para aplicações de tempo real quando o modelo de evento é estável e o transporte é escolhido pelo requisito, não pela moda.
- Infraestrutura de borda — pode ser o fator decisivo entre uma solução elegante e uma solução operacionalmente confiável; buffering e proxies influenciam SSE e WebSockets diretamente.
Leia Também
- node_modules É Um Buraco Negro: Deno e Bun Resolveram Isso
- CORS na prática: segurança no Nginx e no ASP.NET Core
- Background Service e processamento contínuo no .NET
Referências
- ASP.NET Core WebSockets — documentação oficial sobre upgrade de conexão e uso de WebSockets no ASP.NET Core.
- ASP.NET Core SignalR — visão geral oficial de hubs, conexões e transporte.
- MDN: EventSource — API do navegador usada por SSE.
- MDN: WebSocket — API nativa do browser para conexões WebSocket.
- Angular HttpClient — cliente HTTP usado no long polling e na criação das tarefas no demo.
- Microsoft Learn: SignalR client-side JavaScript — integração do cliente SignalR no frontend web.

Ao comentar, você concorda com nossa Política de Privacidade, Termos de Uso e Política de Exclusão de Dados.