Live notifications via Server-Sent Events
Node · Node · intermediate · modification
Upgrades the notifications endpoint from a one-shot snapshot to a live SSE stream. Sets the event-stream headers, flushes them so the browser opens the stream immediately, subscribes to the shared notificationBus, and forwards each event addressed to this user as an SSE frame. Verified against a browser EventSource — notifications show up the instant they fire.
notificationBus is a single process-wide EventEmitter shared by the whole app. Every open browser tab holds one SSE connection, and users open, close, and refresh tabs constantly, so this handler runs on every reconnect against the same long-lived bus.
Requirements
- Turn GET /notifications/stream into a live Server-Sent Events feed: hold the connection open and push each new notification as it arrives, instead of returning a one-shot JSON snapshot.
- Source events from the shared notificationBus and forward only the ones addressed to the connected user.
- No listeners may leak across the connection lifecycle: a client that disconnects must leave nothing behind on the bus.
Files touched
- src/routes/notifications-stream.js
--- src/routes/notifications-stream.js
-const { getUnread } = require('../services/notifications');
+const bus = require('../events/notification-bus');
-// GET /notifications/stream — one-shot JSON snapshot of the user's unread notifications.
-async function streamNotifications(req, res) {
- const unread = await getUnread(req.user.id);
- res.writeHead(200, { 'Content-Type': 'application/json' });
- res.end(JSON.stringify({ unread }));
+// GET /notifications/stream — Server-Sent Events feed of the user's live notifications.
+function streamNotifications(req, res) {
+ res.writeHead(200, {
+ 'Content-Type': 'text/event-stream',
+ 'Cache-Control': 'no-cache',
+ Connection: 'keep-alive',
+ });
+ res.flushHeaders();
+
+ const onNotification = (event) => {
+ if (event.userId !== req.user.id) return;
+ res.write(`event: notification\ndata: ${JSON.stringify(event)}\n\n`);
+ };
+
+ bus.on('notification', onNotification);
}