Connect SSE Middleware

raw JSON →
1.2.0 verified Thu Apr 23 auth: no javascript abandoned

connect-sse is a middleware designed for `connect` (and compatible frameworks like Express) to facilitate the implementation of Server-Sent Events (SSE). It enables servers to push one-way event streams to clients over a persistent HTTP connection, which is commonly used for real-time updates such as live news feeds, stock prices, notifications, and interactive dashboards. The package is currently at version 1.2.0. Based on its last commit in 2013 and a `node` engine requirement of `>=0.10.0`, the project appears to be abandoned and no longer actively maintained or developed. Its primary differentiator is providing a simple, high-level abstraction over raw HTTP streaming for SSE, integrating directly into the `connect` middleware stack. Unlike WebSockets, SSE is strictly unidirectional (server-to-client only), simpler to set up for push notifications, and operates entirely over standard HTTP/1.1, with benefits from HTTP/2 multiplexing for improved efficiency. It lacks native support for modern ESM imports or TypeScript.

error TypeError: sse is not a function
cause The `require('connect-sse')` statement returns a function that must be immediately invoked to get the middleware. Forgetting the `()` after the require call.
fix
Change const sse = require('connect-sse'); to const sse = require('connect-sse')();.
error Cannot use import statement outside a module
cause Attempting to use ES module `import` syntax (`import sse from 'connect-sse'`) in a Node.js environment configured for CommonJS, or for a package that only provides CommonJS exports.
fix
Use the CommonJS require() syntax: const sse = require('connect-sse')();.
error ERR_STREAM_WRITE_AFTER_END
cause Attempting to write to the response stream after the client has disconnected or the stream has been implicitly or explicitly ended. This often happens if cleanup (like `clearInterval` for sending data) is not properly handled on client disconnection.
fix
Implement robust disconnection handling using req.on('close', ...) to stop sending events and clean up resources (e.g., clear setInterval timers) as soon as the client connection is terminated.
breaking The `connect-sse` package is effectively abandoned, with its last known update over a decade ago (2013). This means it receives no security patches, bug fixes, or compatibility updates for newer Node.js versions or web standards.
fix Consider migrating to actively maintained SSE libraries like `better-sse` (npm: better-sse) or implementing SSE directly using native Node.js HTTP response manipulation, especially for new projects or applications requiring ongoing support.
gotcha `connect-sse` is a CommonJS-only module. Attempting to import it using ES module syntax (`import ... from 'connect-sse'`) will result in a runtime error.
fix Always use the CommonJS `require()` syntax: `const sse = require('connect-sse')();`.
gotcha The SSE specification (and thus `connect-sse`) is designed for unidirectional data flow (server-to-client only). If your application requires bi-directional communication, Server-Sent Events are not suitable.
fix For bi-directional communication, consider using WebSockets or other full-duplex communication protocols. SSE is optimized for server-push scenarios like live feeds or notifications.
gotcha Server-Sent Events transmit data as UTF-8 encoded text only. Binary data must be encoded (e.g., Base64) before transmission, which adds overhead.
fix If efficient binary data transfer is critical, WebSockets are a more appropriate technology. For text-based data, SSE works well.
gotcha When not using HTTP/2, SSE connections may be limited to six concurrent connections per browser/domain (a browser-level limitation). While HTTP/2 mitigates this by allowing multiplexing, legacy HTTP/1.1 environments can still hit this ceiling, impacting scalability for many clients.
fix Ensure your server infrastructure supports HTTP/2 to leverage multiplexing for better scalability of SSE connections. Be mindful of this limitation in HTTP/1.1 environments and plan accordingly for a high number of clients.
npm install connect-sse
yarn add connect-sse
pnpm add connect-sse

This quickstart sets up an Express server using connect-sse to stream real-time JSON and plain text events to a client every two seconds. It includes a basic HTML client that uses the native EventSource API to listen for both default 'message' events and a custom 'update' event, displaying them dynamically in the browser.

const express = require('express');
const sse = require('connect-sse')();

const app = express();

app.get('/events', sse, (req, res) => {
  // Set up an interval to send events every 2 seconds
  let counter = 0;
  const intervalId = setInterval(() => {
    if (res.finished) {
      // Client disconnected, clean up interval
      clearInterval(intervalId);
      return;
    }
    const eventData = { timestamp: new Date(), counter: counter++ };
    res.json(eventData, 'update'); // Send a named event 'update'
    res.json(`Plain text message ${counter}`); // Send a default 'message' event
  }, 2000);

  // Ensure the connection closes if the client disconnects
  req.on('close', () => {
    clearInterval(intervalId);
    console.log('Client disconnected, SSE stream closed.');
  });

  console.log('Client connected for SSE stream.');
});

app.get('/', (req, res) => {
  res.send(`
    <!DOCTYPE html>
    <html>
    <head><title>SSE Test</title></head>
    <body>
      <h1>Server-Sent Events Demo</h1>
      <div id="output"></div>
      <script>
        const eventSource = new EventSource('/events');

        eventSource.onmessage = (event) => {
          const p = document.createElement('p');
          p.textContent = `Default message: ${event.data}`;
          document.getElementById('output').appendChild(p);
        };

        eventSource.addEventListener('update', (event) => {
          const data = JSON.parse(event.data);
          const p = document.createElement('p');
          p.textContent = `Update event: Timestamp ${data.timestamp}, Counter ${data.counter}`;
          document.getElementById('output').appendChild(p);
        });

        eventSource.onerror = (error) => {
          console.error('EventSource failed:', error);
          eventSource.close();
        };

        console.log('Client-side EventSource initialized.');
      </script>
    </body>
    </html>
  `);
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`SSE server listening on http://localhost:${PORT}`);
  console.log(`Visit http://localhost:${PORT} in your browser to see events.`);
});