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

Choosing the Right Approach

The decision tree

Do you need the client to send frequent messages to the server?
│
├─ Yes → WebSocket
│   Examples: chat, collaborative editing, games, typing indicators
│
└─ No → Does the server push updates to the client?
    │
    ├─ Yes → SSE
    │   Examples: notifications, live feeds, dashboards, log streaming
    │
    └─ No → REST (no real-time needed)
        Examples: CRUD, reports, settings

If both sides send frequent messages: WebSocket. If only the server pushes: SSE. If neither side needs push: REST.

The hybrid approach

Most production apps use a combination. Our task board uses:

REST for CRUD operations (create task, update task, delete task). These are one-off actions that need request-response semantics: validation errors, status codes, created resource in the response.

SSE for passive viewers. A user viewing a board receives task updates via SSE. They do not need to send anything — they just watch. SSE’s automatic reconnection and event IDs make this reliable.

WebSocket for interactive features. Presence (who is online), typing indicators, and real-time cursor positions require bidirectional communication. The client sends “I am typing” and receives “Bob is typing.”

This is the pattern used by apps like Notion, Linear, and Figma: REST for mutations, real-time channels for updates and collaboration.

Fallback chains

Not every client supports every protocol. Plan for graceful degradation:

Best:   WebSocket
↓ fail: SSE
↓ fail: Long polling
↓ fail: Short polling
// Client-side fallback
function connectRealTime(boardId: string) {
  // Try WebSocket first
  try {
    const ws = new WebSocket(`ws://localhost:3000/ws`);
    ws.onopen = () => {
      ws.send(JSON.stringify({ type: "join", boardId }));
    };
    ws.onmessage = handleEvent;
    ws.onerror = () => fallbackToSSE(boardId);
    return;
  } catch {
    // WebSocket not supported
  }

  fallbackToSSE(boardId);
}

function fallbackToSSE(boardId: string) {
  try {
    const source = new EventSource(`/boards/${boardId}/events`);
    source.onmessage = handleEvent;
    source.onerror = () => fallbackToPolling(boardId);
    return;
  } catch {
    // SSE not supported
  }

  fallbackToPolling(boardId);
}

function fallbackToPolling(boardId: string) {
  setInterval(async () => {
    const res = await fetch(`/boards/${boardId}/updates?since=${lastCheck}`);
    const { data } = await res.json();
    for (const item of data) handleEvent({ data: JSON.stringify(item) });
  }, 5000);
}

In practice, WebSocket and SSE are supported by all modern browsers. Fallbacks are mainly for enterprise environments with restrictive proxies.

Choosing for common use cases

Chat application: WebSocket. Both sides send messages. Typing indicators. Presence. Low latency.

Live dashboard: SSE. Server pushes metrics and updates. The client only displays. Automatic reconnection.

Collaborative document editing: WebSocket. Both sides send edits. Cursor positions. Conflict resolution requires bidirectional real-time.

Notification feed: SSE. Server pushes notifications. Client reads and dismisses. One-way.

Multiplayer game: WebSocket. Low-latency bidirectional. Binary data for game state. Custom protocols.

Stock ticker: SSE. Server pushes price updates. Client displays. High frequency but one-way.

Exercises

Exercise 1: List every real-time feature in your task board. For each, decide: SSE or WebSocket? (Task updates: SSE. Presence: WebSocket. Typing: WebSocket.)

Exercise 2: Implement the fallback chain. Disable WebSocket support (do not start the WS server). Verify the client falls back to SSE.

Exercise 3: Think about an app you use daily. What real-time features does it have? What protocol do you think it uses?

When should you use SSE instead of WebSockets?

← Scaling Real-Time Capstone: Live Task Board →

© 2026 hectoday. All rights reserved.