Processo de envio de dados do server para o front. É apenas uma via, não é possível enviar de volta dados do front para o server.

Padrão do WHATWG (parte da spec HTML), sobre uma conexão HTTP de longa duração. É a peça de padrão web real usada pelo transporte Streamable HTTP (MCP) do MCP.

Mais detalhes em: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events

Formato de wire

Content-Type: text/event-stream, corpo texto plano, eventos separados por linha em branco:

data: primeira parte da resposta

data: segunda parte

event: done
data: {"tokens": 42}

Campos possíveis por evento:

  • data: — payload (múltiplas linhas data: seguidas são concatenadas com \n)
  • event: — tipo do evento (opcional, default message)
  • id: — id do evento, usado pra resumability
  • retry: — tempo em ms que o cliente espera antes de reconectar

Reconexão automática

Diferencial do SSE nativo (EventSource): se a conexão cai, o browser reconecta sozinho, sem lógica de retry manual. Ele reenvia o header Last-Event-ID com o último id: recebido; o servidor decide se faz replay dos eventos perdidos ou continua do zero.

Limitações

  • Unidirecional — cliente não manda nada pela mesma conexão (prompt/input vai por request separado)
  • Limite de conexões por domínio em HTTP/1.1 — browsers limitam a ~6 por origin; some com HTTP/2 (multiplexing)
  • Só texto — binário precisa base64
  • EventSource nativo não suporta headers customizados nem POST — só faz GET, sem body. Pra mandar prompt + histórico (caso de chat), precisa de:
    • fetch + ReadableStream manual (parsing próprio do data: ...\n\n, buffer, AbortController), ou
    • lib @microsoft/fetch-event-source — mesma API do EventSource (parsing, reconexão, Last-Event-ID) mas usa fetch por baixo, aceitando POST/headers/body. Geralmente a melhor escolha, evita reinventar parsing de SSE.

Uso em chatbots (streaming de resposta tipo ChatGPT)

SSE é o recomendado pra esse caso (é o que OpenAI/Anthropic usam), em vez de WebSocket:

  • Unidirecional server→client bate exatamente com o caso de uso
  • Roda sobre HTTP puro — passa por load balancers/CDN/proxy corporativo sem drama (WebSocket exige upgrade de conexão)
  • Modelo mental bate 1:1 com geração token-by-token — cada data: é um chunk, evento final (event: done ou data: [DONE]) sinaliza fim

WebSocket só compensa se precisar de baixa latência bidirecional simultânea (ex: interromper geração + mandar novo input ao mesmo tempo), voice/real-time multimodal, ou stream colaborativo com múltiplos participantes. Cancelamento de geração dá pra fazer com AbortController sem precisar de full duplex.

Ver também