Frontend Development 10 min read

Mastering Server‑Sent Events (EventSource) in JavaScript: Real‑Time Updates Made Easy

This article explains how Server‑Sent Events (SSE) and the EventSource API enable real‑time, one‑way data streams in web pages, covering browser support, key features, client‑side usage, server implementation, data formatting rules, and practical tips for reliable deployment.

Code Mala Tang
Code Mala Tang
Code Mala Tang
Mastering Server‑Sent Events (EventSource) in JavaScript: Real‑Time Updates Made Easy

With the rise of ChatGPT, many developers have discovered the simple yet powerful effect of displaying text character‑by‑character, which relies on the streaming request technology known as Server‑Sent Events (SSE). SSE is a one‑way communication protocol that pushes real‑time updates from the server to the client, ideal for news feeds, social notifications, stock quotes, and similar scenarios.

EventSource in JavaScript

In JavaScript the API is called EventSource , a ten‑year‑old feature that is part of the HTML5 specification. It allows a web page to receive data over a standard HTTP connection without polling.

Browser support timeline

Firefox : first supported EventSource in version 4.0 (March 2011)

Chrome : added support in version 9.0 (November 2010)

Safari : supported from version 6.0 (July 2012)

Internet Explorer : supported from version 10.0 (October 2012)

Key characteristics of EventSource

One‑way communication : server pushes messages, client cannot send via the same channel.

Text stream : data is sent as UTF‑8 text.

Automatic reconnection : browsers retry automatically if the connection drops.

Event naming : messages can carry a custom event type for selective handling.

Using EventSource on the client

<code>// Create a new EventSource object pointing to the SSE endpoint
const eventSource = new EventSource('server-sent-events-url');
// Listen for the default message event
eventSource.onmessage = function(event) {
  console.log('Received message:', event.data);
};
// Listen for a custom event
eventSource.addEventListener('customEvent', function(event) {
  console.log('Received custom event:', event.data);
});
// Listen for errors
eventSource.onerror = function(event) {
  console.error('EventSource error:', event);
};
</code>

The constructor accepts two arguments: the URL and an optional configuration object. The only option is withCredentials (default false ), which controls whether CORS requests include credentials.

An EventSource instance opens a persistent HTTP connection that streams events in text/event-stream format until eventSource.close() is called.

Server‑side implementation

<code>const http = require('http');
http.createServer((req, res) => {
  if (req.url === '/events') {
    res.writeHead(200, {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive'
    });
    // Send a custom event every 3 seconds
    setInterval(() => {
      res.write(`event: sourceEvent\n`);
      res.write(`data: Custom event message - ${new Date().toLocaleTimeString()}\n\n`);
    }, 3000);
    // Keep the connection alive
    setInterval(() => {
      res.write(': keep-alive\n\n');
    }, 15000);
  } else {
    res.writeHead(404);
    res.end();
  }
}).listen(8080, () => {
  console.log('Server running at http://localhost:8080');
});
</code>

If you only need to send plain data, you can omit the custom event name and write directly:

<code>setInterval(() => {
  res.write(`data: ${new Date().toLocaleTimeString()}\n\n`);
}, 1000);
</code>

The data lines must follow the SSE format:

<code>data: This is a message
event: customEvent
data: Message with an event type
retry: 5000  // Reconnection interval in ms
</code>

Important notes

1. Comment lines : Lines starting with a colon (:) are treated as comments and are ignored by the browser, but they help keep the connection alive.

2. Required prefixes : Each line must begin with one of the keywords data , event , id , retry , or : to be recognized by the client.

3. Mandatory HTTP headers : The response must include Content-Type: text/event-stream , Cache-Control: no-cache , and Connection: keep-alive so browsers understand the stream.

4. Parameters : Since SSE is server‑to‑client only, any needed parameters must be passed via the URL query string.

5. Browser connection limits : Without HTTP/2, browsers typically allow only six concurrent SSE connections per domain, which can become a bottleneck when many tabs are open. HTTP/2 raises the limit (default 100) through client‑server negotiation.

6. Avoiding timeout disconnects : Periodically send a comment line (e.g., : keep-alive ) to prevent intermediate network devices from closing the idle connection.

Conclusion

EventSource provides a lightweight, easy‑to‑use solution for real‑time data updates on web pages, eliminating the need for manual refreshes. Its simplicity and broad browser support make it ideal for applications that require frequent updates, such as live feeds or dashboards.

Next time you need live updates, give EventSource a try and experience how effortless real‑time communication can be. In future articles we’ll explore related streaming APIs like WritableStream , ReadableStream , and TransformStream .

real-timeJavaScriptWeb DevelopmentServer-Sent EventsSSEEventSource
Code Mala Tang
Written by

Code Mala Tang

Read source code together, write articles together, and enjoy spicy hot pot together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.