Server-Sent Events (SSE): Simplified Real-Time Communication
17-12-2025
In web development, there are contexts where communication between client and server cannot be satisfied with the default HTTP request-response communication, such as in the case of instant notifications, updates, or partial resolution of information. Server-Sent Events (SSE) provide a good solution compared to others like web sockets. In this article, I'll explain how they work and when to use them. This all arises from studying it to apply it in the context of applications that use AI, allowing the streaming of agent processing in response to a user's request.
What are SSE?
Server-Sent Events (SSE) allow the server to send data continuously and unidirectionally to a client (such as a browser) after a single initial connection. Unlike classic HTTP requests (where the client repeatedly asks), with SSE the server pushes information as soon as it is available. It's like a radio broadcast: the server transmits, the client listens.
Main Features
-
Unidirectional communication The flow goes from the server to the client, not the other way around.
-
Text event format Messages are sent as text with a specific syntax. Each event ends with a blank line (
\n\n). Example:data: {"stock": "GOOG", "price": 1500} -
Native API in browsers:
EventSourceNo external libraries. Basic example:const source = new EventSource("/stock-updates"); source.addEventListener("message", (event) => { console.log(event.data); // Contains the server payload }); -
Automatic reconnection If the connection drops, the browser automatically retries. According to the HTML specification, the reconnection time is defined by the implementation, typically a few seconds. The server can suggest the interval with
retry::retry: 5000 data: Welcome -
Event identifiers (
id) Allow resuming without losing data. When the client reconnects, it sends theLast-Event-IDheader with the last receivedid, and the server can continue from there (HTML specification):id: 123 data: {"stock": "GOOG", "price": 1500} id: 124 data: {"stock": "GOOG", "price": 1502}
Example with Node.js and Express: AI Agent with ReAct Pattern
Server (SSE endpoint for AI agent):
app.get("/ai-agent", (req, res) => { res.setHeader("Content-Type", "text/event-stream"); res.setHeader("Cache-Control", "no-cache"); res.setHeader("Connection", "keep-alive"); let aborted = false; req.on("close", () => { aborted = true; }); // Helper to wait const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); // Function to send SSE events const sendEvent = (res, id, data) => { if (aborted) return; res.write(`id: ${id}\n`); res.write(`data: ${JSON.stringify(data)}\n\n`); }; // Simulation of AI agent steps with ReAct (it would be a while loop if we had a real agent) // each step sends an SSE event that the client can process and decide how to act to render the information (async () => { sendEvent(res, 1, { type: "reasoning", content: "Analyzing the user's query..." }); await sleep(1000); sendEvent(res, 2, { type: "action", content: "Searching for information in the database..." }); await sleep(1000); sendEvent(res, 3, { type: "observation", content: "Found 3 relevant results" }); await sleep(1000); sendEvent(res, 4, { type: "reasoning", content: "Evaluating the best response based on the data..." }); await sleep(1000); sendEvent(res, 5, { type: "action", content: "Generating final response..." }); await sleep(1000); sendEvent(res, 6, { type: "result", content: "Here is the information you requested..." }); await sleep(1000); sendEvent(res, 7, { type: "final", content: "Process completed." }); res.end(); })(); });
SSE vs Polling vs WebSockets
-
REST + Polling The client asks periodically (e.g., every 5s). Simple but inefficient and with higher latency.
-
SSE Ideal when the client only receives real-time data: notifications, feeds, tickers, prices. More efficient than polling and easy to implement. MDN recommends SSE for unidirectional server-to-client communication.
-
WebSockets Bidirectional communication. Perfect for chats, multiplayer games, collaborative editing. If the client also needs to send data interactively and constantly, WebSockets is usually the option.
Important Note: According to MDN, SSE has limitations on the number of concurrent connections when not using HTTP/2 (6 connections per domain in most browsers).
Advantages of SSE
- Simple implementation with native API (
EventSource) available in all modern browsers. - Automatic reconnection and integrated event handling according to HTML specification.
- Lower consumption than polling (fewer requests, lower perceived latency).
- Works over HTTP/1.1 and fits well with existing infrastructure.
- Simple and understandable text format (
text/event-stream).
Conclusion
Server-Sent Events are an excellent solution when the client needs to listen to real-time updates efficiently and easily. For cases of bidirectional interaction (chats, collaboration, or games), WebSockets will generally be the appropriate choice. In my current project, SSE fits very well to open a connection during an interaction with an AI agent that reports its progress or work plan as it executes it in a loop until it provides a final result that also triggers the closure of the communication and request.
References and Sources
- HTML Living Standard - Server-sent events - WHATWG (Official Specification)
- MDN Web Docs - Server-sent events - Mozilla Developer Network
- MDN Web Docs - Using server-sent events - Practical implementation guide
- JavaScript.info - Server Sent Events - Detailed tutorial with examples
