hectoday
DocsCoursesChangelog GitHub
DocsCoursesChangelog GitHub

Access Required

Enter your access code to view courses.

Invalid code

← All courses Real-Time APIs with @hectoday/http

Beyond Request-Response

  • Why Real-Time Matters
  • Project Setup

Polling

  • Short Polling
  • Long Polling

Server-Sent Events

  • How SSE Works
  • Building an SSE Endpoint
  • Event Types and IDs
  • SSE in Practice

WebSockets

  • How WebSockets Work
  • Building a WebSocket Server
  • Rooms and Broadcasting
  • Authentication on WebSockets
  • Handling Disconnects and Reconnection

Patterns and Architecture

  • Pub/Sub
  • Presence
  • Scaling Real-Time

Putting It All Together

  • Choosing the Right Approach
  • Capstone: Live Task Board

How SSE Works

One persistent connection, many events

Server-Sent Events (SSE) solve the long-polling problems with a simpler model: the client opens one connection, and the server pushes events through it whenever data is available. The connection stays open indefinitely.

Unlike long polling (where the connection closes after each event and the client reconnects), SSE keeps the same connection open. The server streams events as they happen.

The protocol

SSE uses a plain HTTP response with Content-Type: text/event-stream. The body is a stream of text events, each separated by double newlines:

data: {"type":"task_created","task":{"id":"task-5","title":"New task"}}

data: {"type":"task_moved","task":{"id":"task-3","listId":"list-done"}}

data: {"type":"task_deleted","taskId":"task-2"}

Each event is a data: line followed by a blank line. That is the entire protocol.

The browser API

Browsers have a built-in EventSource API for SSE:

// Client-side
const source = new EventSource("/boards/board-1/events");

source.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log("Event:", data.type, data);
  updateUI(data);
};

source.onerror = () => {
  console.log("Connection lost. Reconnecting...");
  // EventSource reconnects automatically
};

Three lines to set up a real-time connection. The browser handles reconnection, buffering, and connection management.

Automatic reconnection

When the connection drops (network issue, server restart), EventSource reconnects automatically after a short delay (typically 3 seconds). The client does not need to implement reconnection logic — it is built into the browser.

The server can control the reconnection delay:

retry: 5000

data: {"type":"task_created","task":{"id":"task-5"}}

The retry: field tells the browser to wait 5 seconds before reconnecting (instead of the default 3).

SSE vs long polling

FeatureLong pollingSSE
ConnectionCloses after each eventStays open
ReconnectionClient implementsBrowser automatic
Multiple eventsOne per connection cycleMany per connection
ProtocolStandard HTTP responsetext/event-stream
Browser APIfetch (manual)EventSource (built-in)
DirectionServer → clientServer → client

SSE is simpler, more efficient, and has better browser support than long polling. Use long polling only as a fallback for environments that do not support SSE.

Exercises

Exercise 1: Open a terminal and send a raw SSE response with curl: curl -N http://localhost:3000/boards/board-1/events. (The endpoint does not exist yet — we build it in the next lesson.)

Exercise 2: In a browser console, create an EventSource connection to any endpoint that returns text/event-stream. Observe the onmessage callbacks.

Exercise 3: Read the MDN documentation on EventSource. What happens when the connection drops? (Answer: onerror fires, then the browser reconnects automatically after the retry interval.)

What is the key advantage of SSE over long polling?

← Long Polling Building an SSE Endpoint →

© 2026 hectoday. All rights reserved.