A Complete Developerโs Guide with Node.js, React, React Native, and Next.js
๐ง 1. What is Server-Sent Events (SSE)?
Server-Sent Events (SSE) is a unidirectional streaming protocol built into modern browsers. It allows servers to push real-time updates to the client over a single long-lived HTTP connection using the EventSource API.
Think of it as a reverse
fetchโonce initiated, the server keeps sending data as events happen.
๐ Key Characteristics
- Built on HTTP/1.1 (no WebSocket upgrade needed)
- Text/event-stream content type
- Auto-reconnect mechanism by the browser
- Low overhead, lightweight, easy to implement
๐ฏ 2. When to Use SSE?
SSE shines in server-to-client real-time delivery scenarios, especially where simplicity and HTTP compatibility are key.
๐ง Common Use Cases
| Use Case | Why SSE Fits Well |
|---|---|
| ๐ Notifications | Push updates to logged-in users instantly |
| ๐ Live Dashboards | Periodic updates to analytics or KPIs |
| ๐ฐ Real-Time News Feeds | Auto-refreshing breaking news |
| โฑ๏ธ Tickers & Clocks | Update countdowns or current time |
| ๐ก IoT Device Updates | Sensor streams without bidirectional need |
โ ๏ธ Use WebSocket when you require two-way communication (e.g. chat, multiplayer games).
โ๏ธ 3. How SSE Works
๐ค Server Response
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
Each message sent must:
- Start with
data:and end with two newlines - Optionally include:
id:,event:,retry:
๐ Message Format
data: {"message":"Hello, client!"}
data: {"time":"2025-08-02T12:00:00Z"}
๐งช Basic JavaScript Client
const es = new EventSource("http://localhost:4000/events");
es.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log("Received:", data);
};
es.onerror = () => {
console.warn("Connection lost. Reconnecting...");
};
๐ ๏ธ 4. Node.js Express SSE Server Example
const express = require("express");
const cors = require("cors");
const app = express();
app.use(cors());
app.get("/events", (req, res) => {
res.setHeader("Content-Type", "text/event-stream");
res.setHeader("Cache-Control", "no-cache");
res.setHeader("Connection", "keep-alive");
const send = () => {
const payload = JSON.stringify({ time: new Date().toISOString() });
res.write(`data: ${payload}\n\n`);
};
send(); // Send initial data immediately
const interval = setInterval(send, 5000);
req.on("close", () => {
clearInterval(interval);
console.log("Cleanup: Client disconnected");
});
});
app.listen(4000, () => console.log("SSE server running on port 4000"));
โ Tip: Add
res.flush()if usingcompressionmiddleware (to push chunks immediately).
๐ป 5. SSE Clients
๐ React (Web)
import { useEffect, useState } from "react";
export default function SSEComponent() {
const [time, setTime] = useState("");
useEffect(() => {
const es = new EventSource("http://localhost:4000/events");
es.onmessage = (e) => {
const data = JSON.parse(e.data);
setTime(data.time);
};
es.onerror = () => {
console.warn("SSE connection error");
};
return () => es.close();
}, []);
return <div>Server Time: {time}</div>;
}
๐ฑ React Native (Mobile)
npm install react-native-event-source
Alternative Packages:
- https://www.npmjs.com/package/react-native-sse
- https://www.npmjs.com/package/@ammarahmed/react-native-eventsource
import EventSource from "react-native-event-source";
import { useEffect } from "react";
export default function LiveStream() {
useEffect(() => {
const es = new EventSource("http://192.168.1.x:4000/events");
es.onmessage = (event) => {
console.log("Data:", event.data);
};
return () => es.close();
}, []);
return null;
}
โ ๏ธ Use IP instead of
localhostand ensure both devices are on the same network.
โ๏ธ Next.js (Client Component)
"use client";
import { useEffect, useState } from "react";
export default function Page() {
const [data, setData] = useState("");
useEffect(() => {
const es = new EventSource("/api/events");
es.onmessage = (e) => {
setData(JSON.parse(e.data).time);
};
return () => es.close();
}, []);
return <div>Time: {data}</div>;
}
๐งช Next.js API Route (SSE Handler)
export function GET(req: Request) {
const encoder = new TextEncoder();
const stream = new ReadableStream({
start(controller) {
const interval = setInterval(() => {
const data = `data: ${JSON.stringify({
time: new Date().toISOString(),
})}\n\n`;
controller.enqueue(encoder.encode(data));
}, 5000);
req.signal.addEventListener("abort", () => {
clearInterval(interval);
controller.close();
});
},
});
return new Response(stream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
},
});
}
๐ 6. Advanced SSE Features
Custom Event Types
res.write("event: customEvent\n");
res.write(`data: {"message":"Custom event triggered!"}\n\n`);
es.addEventListener("customEvent", (e) => {
console.log("Custom Event:", e.data);
});
Retry Delay Control
retry: 10000
data: {"message":"Retry in 10s"}
Client waits 10 seconds before reconnecting.
โ๏ธ 7. Pros and Cons
โ Pros
- Native browser API (
EventSource) - No third-party library needed
- Simple, scalable (good for thousands of clients)
- Works well with HTTP infrastructure
โ Cons
- One-way only
- Not supported in all mobile environments (needs polyfill)
- Needs proxy tweaks (e.g., Cloudflare, Nginx)
- No binary or structured message formats (text-only)
๐ 8. SSE vs WebSocket
| Feature | SSE | WebSocket |
|---|---|---|
| Direction | Server โก๏ธ Client | Bidirectional |
| Protocol | HTTP/1.1 | WS (Upgrade from HTTP) |
| Browser Support | Most browsers | All modern browsers |
| Complexity | Low | MediumโHigh |
| Streaming | Text-only | Binary, JSON, Text |
| Mobile Support | Polyfill required | Native |
| Reconnect | Built-in basic retry | Manual handling required |
๐งฑ 9. Production Considerations
- โ Disable compression middleware to prevent buffered messages
- โ Turn off proxy buffering (e.g., Nginx)
location /events {
proxy_pass http://localhost:4000;
proxy_buffering off;
chunked_transfer_encoding off;
}
- โ
Use heartbeats (e.g.,
data:\n\n) to keep connections alive - โ
Reconnection logic: Use
es.onerrorores.readyStatechecks
๐ 10. Alternatives
| Tech | Direction | Transport |
|---|---|---|
| WebSocket | Two-way | WebSocket |
| Socket.IO | Two-way + fallback | WebSocket, polling |
| GraphQL Subscriptions | Two-way (GraphQL) | WebSocket |
| Firebase | Two-way | Proprietary |
| Pusher / Ably | Pub/Sub | WebSocket / HTTP |
| Kafka REST Proxy | One-way stream | HTTP/REST |
โ 11. Conclusion
Server-Sent Events are a lightweight, simple, and scalable way to stream real-time data from server to client using nothing but HTTP and vanilla JavaScript.
Theyโre a perfect fit for dashboards, notifications, live feeds, and IoT monitoringโespecially when you donโt need two-way communication.
Use SSE when simplicity and scalability matter. Use WebSocket when interaction matters.
๐ 12. Resources
- ๐ MDN โ Server-sent Events
- ๐ WHATWG Spec
- ๐ฑ React Native EventSource
- ๐ฆ Node.js EventSource Polyfill
Top comments (0)