DEV Community

Cover image for ๐Ÿ”ฅ Real-Time Data Streaming with Server-Sent Events (SSE)
Serif COLAKEL
Serif COLAKEL

Posted on

๐Ÿ”ฅ Real-Time Data Streaming with Server-Sent Events (SSE)

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
Enter fullscreen mode Exit fullscreen mode

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"}
Enter fullscreen mode Exit fullscreen mode

๐Ÿงช 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...");
};
Enter fullscreen mode Exit fullscreen mode

๐Ÿ› ๏ธ 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"));
Enter fullscreen mode Exit fullscreen mode

โœ… Tip: Add res.flush() if using compression middleware (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>;
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿ“ฑ React Native (Mobile)

npm install react-native-event-source
Enter fullscreen mode Exit fullscreen mode

Alternative Packages:

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;
}
Enter fullscreen mode Exit fullscreen mode

โš ๏ธ Use IP instead of localhost and 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>;
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿงช 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",
    },
  });
}
Enter fullscreen mode Exit fullscreen mode

๐Ÿ” 6. Advanced SSE Features

Custom Event Types

res.write("event: customEvent\n");
res.write(`data: {"message":"Custom event triggered!"}\n\n`);
Enter fullscreen mode Exit fullscreen mode
es.addEventListener("customEvent", (e) => {
  console.log("Custom Event:", e.data);
});
Enter fullscreen mode Exit fullscreen mode

Retry Delay Control

retry: 10000
data: {"message":"Retry in 10s"}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode
  • โœ… Use heartbeats (e.g., data:\n\n) to keep connections alive
  • โœ… Reconnection logic: Use es.onerror or es.readyState checks

๐Ÿ”„ 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


Top comments (0)