Express Server-Sent Events Middleware

raw JSON →
3.0.3 verified Thu Apr 23 auth: no javascript

express-sse-middleware is an npm package providing a robust Express.js middleware for implementing Server-Sent Events (SSE) in Node.js applications. It simplifies the process of pushing real-time updates from a server to clients over a single HTTP connection, making it suitable for dashboards, chat applications, and live data feeds. The current stable version is 3.0.3, released after a significant v3.0.0 update which transitioned the package to an ES Module (ESM) first architecture. While a strict release cadence isn't explicitly defined, the package appears actively maintained given recent major version bumps and ongoing development. Its primary differentiator is its straightforward integration into existing Express applications by extending the `Response` object with a dedicated `sse()` method, allowing developers to easily send data, custom events, and IDs to connected clients. It also offers an `EventBuilder` for more structured event creation, though direct string sending is fully supported and often sufficient for simple use cases.

error TypeError: res.sse is not a function
cause The `sseMiddleware` was not correctly applied to the Express application using `app.use()`, or the route attempting to use `res.sse()` is defined before `app.use(sseMiddleware)`.
fix
Ensure app.use(sseMiddleware); is called at an appropriate point in your Express application setup, typically before any routes that utilize SSE features.
error ReferenceError: require is not defined in ES module scope
cause You are attempting to use CommonJS `require()` syntax (e.g., `const { sseMiddleware } = require('express-sse-middleware');`) in an ES Module project, which is incompatible with `express-sse-middleware` v3+.
fix
Update your import statements to use ES Module syntax (e.g., import { sseMiddleware } from 'express-sse-middleware';) and ensure your package.json specifies "type": "module".
error Failed to load resource: net::ERR_NAME_NOT_RESOLVED (or similar CORS error in browser console)
cause Your client-side application is attempting to connect to the SSE server from a different origin (domain, port, or protocol) without the necessary Cross-Origin Resource Sharing (CORS) headers configured on the server.
fix
Install and use the cors middleware in your Express application: npm install cors then import cors from 'cors'; app.use(cors({ origin: 'http://your-client-app-domain.com' }));.
breaking Version 3.0.0 of `express-sse-middleware` transitioned the package to be ES Module (ESM) first. Projects using CommonJS (`require()`) must either migrate to ESM or use an older 2.x version of the middleware.
fix Ensure your `package.json` includes `"type": "module"` and use `import` statements for all modules. For TypeScript, ensure `"module": "NodeNext"` or `"ESNext"` is configured in `tsconfig.json`.
gotcha SSE connections are persistent and remain open until explicitly closed by the server or client. Failing to clean up resources (e.g., `setInterval`, database listeners) upon client disconnection can lead to memory leaks and performance degradation.
fix Attach a 'close' event listener to the `req` object (`req.on('close', () => { /* cleanup code */ });`) to ensure all allocated resources for that specific client connection are released.
gotcha Server-Sent Events do not automatically handle cross-origin requests. If your client-side application is hosted on a different domain, port, or protocol than your SSE server, the browser will block the connection due to CORS policies.
fix Install and configure the `cors` middleware (e.g., `npm install cors`) in your Express application. Add `app.use(cors({ origin: 'http://your-client-domain.com' }));` before your SSE route to allow the connection.
gotcha While SSE has built-in reconnection logic in browsers, the server-side needs to be prepared to handle new connections from clients that might be retrying after a network interruption or server restart.
fix Ensure your SSE route logic is stateless for new connections, or can gracefully re-establish context for a client if necessary. Design client-side to use `EventSource` which handles retries, or implement custom retry logic.
npm install express-sse-middleware
yarn add express-sse-middleware
pnpm add express-sse-middleware

Sets up an Express server to push continuously incrementing numbers to clients every second over a Server-Sent Events connection, demonstrating basic usage and crucial client disconnect cleanup.

import express from 'express';
import { sseMiddleware } from 'express-sse-middleware';

const app = express();
const PORT = 3000;

app.use(sseMiddleware);

app.get('/events', (req, res) => {
  // Set appropriate headers for SSE. This is handled by sseMiddleware but good to know.
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
  });

  const sse = res.sse(); // Adds the sse() function to the Response object
  let count = 0;

  const intervalId = setInterval(() => {
    sse.send(String(count++), 'message', 'update-id-' + (count - 1)); // data, eventName, id
  }, 1000);

  // Essential cleanup: Remove resources when client disconnects to prevent memory leaks
  req.on('close', () => {
    console.log('Client disconnected. Cleaning up interval.');
    clearInterval(intervalId);
    // You might also want to end the response if it hasn't been already, though SSE implies an open connection.
    // res.end();
  });

  console.log('New client connected for SSE updates.');
});

app.listen(PORT, () => {
  console.log(`SSE server listening on http://localhost:${PORT}/events`);
  console.log('To test: Open a browser and navigate to http://localhost:3000/events or use a client-side EventSource API.');
});