Oito segundos encarando um spinner matam a conversão; os mesmos oito segundos chegando em chunks dão sensação de resposta imediata. Streaming de respostas de IA derruba a latência percebida de 8s para menos de 1s porque o primeiro token chega rápido e o resto flui, e a taxa de abandono cai junto. Na maioria dos casos, Server-Sent Events entrega isso com bem menos complexidade que WebSockets.
Como funciona o SSE
SSE é HTTP puro: resposta com content type text/event-stream, eventos separados por linha em branco e reconexão automática embutida no EventSource do navegador. Cada evento cabe em poucos bytes, então proxies e balanceadores lidam bem com o fluxo. Conexão ociosa morre em proxy intermediário; um comentário de keepalive (: ping a cada 15s) mantém o caminho aberto. Para LLM, em que o fluxo vai do servidor ao cliente, SSE entrega tudo que WebSockets oferece com um request HTTP comum.
Quando WebSockets compensam?
- Fluxo bidirecional real: agentes de voz, sessões colaborativas, interrupção do usuário no meio da fala
- Latência de mensagem abaixo de 100ms muda a experiência percebida
- Multiplexação de várias streams lógicas numa conexão única
Streaming de tokens no backend
O servidor encaminha os deltas do provedor conforme chegam e descarrega buffers sem esperar acumular. O nginx segura chunks por padrão e queima a experiência: proxy_buffering off; na location ou o header X-Accel-Buffering: no na resposta resolvem. Compressão gzip em respostas parciais também retém bytes; desative-a nesse endpoint.
Cancelamento: pare de pagar tokens invisíveis
Usuário clicou em stop? O cliente aborta o fetch, o servidor detecta a conexão fechada (request.on('close') no Express, cancelamento de generator no FastAPI) e encerra a chamada upstream no provedor. Provedores cobram pelos tokens gerados até o corte, então o corte precisa acontecer dos dois lados. Registre o cancelamento nos logs com o ID da sessão; o suporte agradece quando o usuário relata resposta cortada. Sem essa cadeia, toda sessão abandonada paga tokens que ninguém leu.
Erros no meio do stream
O provedor derruba a conexão após metade da resposta. Envie o que chegou mais um evento final de erro estruturado; o cliente renderiza o parcial com marcador claro de falha e botão de regenerar. Quando o provedor suporta continuação, regenere a partir do último chunk recebido. Silêncio até o timeout é a alternativa ruim.
Notas por framework
- Next.js: route handlers streamam
ReadableStreamsem biblioteca extra - Express: headers
Content-Type: text/event-stream,Cache-Control: no-cacheeConnection: keep-alive, comres.flush()após cada chunk - FastAPI:
StreamingResponsede fábrica consumindo generators async
Curtiu o conteúdo?
Construo produtos web e soluções com IA do jeito certo — arquitetura sólida, código sustentável e entrega real.
Vamos conversar