SSE for Chat Developers: Live Replies in Five Minutes
§1 SSE turns one HTTP response into live chat updates
A streaming chat interface should show the answer while the model is generating it, not after the entire response finishes. Server-sent events, or SSE, provide a straightforward way to deliver those incremental updates over HTTP.
The server keeps a response open and sends small text events as new content becomes available. Your interface reads each event and extends the assistant’s message. Updates often contain text fragments rather than exactly one token, so treat them as incremental content, not individual words.
For a five-minute quick start, focus on three things: recognize the event format, request a streaming response, and connect that response to your chat interface.
§2 Minute one: recognize SSE event boundaries
An SSE response uses the Content-Type header text/event-stream. Each event consists of text fields and ends with a blank line. A simple event contains a data: field followed by its payload.
For example, an event might carry data: {"text":"Hello"}, followed by two newline characters. The next event might contain another text fragment. Your application combines those fragments into the visible reply.
- – data: carries the event payload, often serialized JSON.
- – event: optionally names an event type, such as a content update or application error.
- – id: optionally identifies an event for applications that support resuming delivery.
Transport chunks are not SSE events. A network read can contain half an event or several complete events. Keep an unfinished buffer between reads, recognize blank-line boundaries, and parse only complete events.
§3 Minute two: request an actual token stream
For an OpenAI-style chat endpoint, send a JSON request with stream set to true. A quick terminal test is:
curl -N https://api.fluxioapi.com/v1/chat/completions -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" -d '{"model":"YOUR_MODEL_ID","messages":[{"role":"user","content":"Explain SSE in three sentences."}],"stream":true}'
Replace the key and model placeholder before running the command. Use the provider’s documented API identifier rather than assuming a display name is the identifier. For example, you could select Gemini 2.5 Flash if it is available in your account. The curl -N option disables curl’s output buffering so incoming events appear promptly.
Fluxio fits this workflow as a streaming-first, pay-per-token AI API relay. Its API base is https://api.fluxioapi.com; OpenAI-style clients use https://api.fluxioapi.com/v1. One key provides access to multiple model providers, making it practical to test streaming behavior without building separate integrations.
§4 Minute three: relay the stream through your backend
Create a backend route such as POST /api/chat. Accept the conversation, call the upstream chat endpoint with streaming enabled, and forward the response incrementally. Store the API key on the server, never in browser code.
When forwarding SSE unchanged, preserve its framing and send text/event-stream to the browser. Disable buffering in your framework and reverse proxy where necessary. For sensitive responses, use an appropriate no-store cache policy.
Handle upstream HTTP errors before starting a successful streaming response. If generation fails after streaming begins, send a defined application error event when possible, then close the connection.
§5 Minute four: render deltas with fetch
Native EventSource is convenient for GET-based subscriptions, but a chat request usually needs a POST body. Use fetch with your conversation JSON, then read response.body incrementally.
Decode bytes with TextDecoder in streaming mode, feed the text into an SSE parser, and inspect each parsed payload. In OpenAI-style chat chunks, text commonly appears in choices[0].delta.content. Append only content-bearing deltas; other chunks can carry role, tool-call, finish, or usage information.
Use an SSE parser library rather than assuming every read contains one JSON object. Handle the endpoint’s completion convention, such as data: [DONE], without trying to parse that marker as JSON.
§6 Minute five: test cancellation and interrupted replies
Give the user a Stop button backed by AbortController, and propagate cancellation upstream from your backend. Test a disconnected browser, a slow connection, and a proxy that buffers output. Mark interrupted replies clearly instead of silently treating partial text as complete.
SSE is one-way delivery, which suits assistant replies well. Keep conversation state separately, and do not assume reconnecting can resume a generation unless your backend explicitly supports replay.
Sign up for Fluxio to try live token streams.