Realtime Channels

Set up WebSocket connections for live data updates, chat, and collaborative features in Spala.

Realtime Channels

Realtime channels provide WebSocket connections for pushing live data to connected clients. Use them for features that require instant updates — chat applications, live notifications, collaborative editing, real-time dashboards, and multiplayer experiences.

Check availability first

If Realtime Channels are not visible in your project, use endpoints, triggers, and your frontend realtime provider until Channels are enabled for your workspace.

Frontend handoff requirement

Realtime is project-specific. Before assigning frontend work, copy the selected channel's WebSocket path, auth mode, permissions, subscribe envelope, event examples, heartbeat interval, close codes, replay behavior, and reconnect expectations into the External Frontend Handoff packet.

Spala Realtime Channels workspace showing channel list, stats, and editor
Realtime Channels show connected clients, active channels, active subscriptions, and message throughput.

Channel Types

- Database Changes - emit events when selected tables change.
- Broadcast - send messages to all or selected subscribers.
- Presence - track who is connected and update clients when presence changes.

How Realtime Channels Work

Unlike REST endpoints where the client sends a request and waits for a response, WebSocket channels maintain a persistent connection between the client and server. This allows the server to push data to clients at any time without the client having to poll.

1. A client opens a WebSocket connection to a channel
2. The server authenticates the connection (if configured)
3. The client subscribes to the channel and optionally to specific topics
4. The server pushes messages to connected clients when events occur
5. Clients can also send messages to the server through the same connection

Creating a Realtime Channel

Navigate to the Channels section in the left sidebar

Click New Channel and select Realtime

Enter a channel name (e.g., "Live Updates")

Set the path for WebSocket connections (e.g., /ws)

Configure authentication and event handlers

Save the channel

Channel Configuration

Event Handlers

Realtime channels support three event handler functions:

On Connect

Runs when a new client connects to the channel. Use this to initialize client state, join rooms, or send a welcome message.

// On Connect handler

// vars.ws.clientId   → unique connection identifier
// vars.ws.auth       → decoded JWT payload (if auth is enabled)
// Step 1: Log the connection
// Step 2: Send welcome message to the client
// ws.send({ type: "welcome", message: "Connected to live updates" })

On Message

Runs when a client sends a message through the WebSocket connection. The message payload is available as vars.ws.message.

// On Message handler

// vars.ws.clientId → who sent the message
// vars.ws.message  → the parsed message object
// Step 1: Condition - Check message type
// If vars.ws.message.type === "chat"
//   Step 2: Broadcast to all connected clients
//   ws.broadcast({ type: "chat", user: vars.ws.auth.name, text: vars.ws.message.text })

On Disconnect

Runs when a client disconnects. Use this to clean up resources, update presence status, or notify other clients.

// On Disconnect handler

// Step 1: Database Query - Update user status
// UPDATE users SET status = 'offline' WHERE id = vars.ws.auth.userId
// Step 2: Broadcast presence update
// ws.broadcast({ type: "presence", userId: vars.ws.auth.userId, status: "offline" })

Sending Messages

There are several ways to send messages to connected clients:

From a Handler Function

Within a realtime channel handler, use the WebSocket step actions:

- ws.send(data) — Send a message to the current client only
- ws.broadcast(data) — Send a message to all connected clients on this channel
- ws.broadcastToOthers(data) — Send to all clients except the sender

From Any Function

Any endpoint, task, or trigger function can push a message to a realtime channel using the Send to Channel step:

// In an endpoint function — notify clients when an order is updated

// Step 1: Database Query - Update the order
// UPDATE orders SET status = 'shipped' WHERE id = input.orderId
// Step 2: Send to Channel - "Live Updates"
// Message: { type: "order.updated", orderId: input.orderId, status: "shipped" }

The Send to Channel step lets any part of your application push realtime updates. This means your REST endpoints can trigger live updates without the client needing to poll.

Client-Side Connection

Connect to a realtime channel from JavaScript using the standard WebSocket API:

const ws = new WebSocket('wss://<your-project-host>/ws?token=' + encodeURIComponent(token));

ws.onopen = () => {
  console.log('Connected to realtime channel');
};
ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log('Received:', data);
};
ws.onclose = () => {
  console.log('Disconnected');
};

Browser WebSocket clients cannot set arbitrary Authorization headers. Use the authentication method your Spala channel exposes, such as a token query parameter, cookie, or subprotocol.

Client Message Contract

The exact channel path, auth mode, event names, and payloads are project-specific. Export or copy the generated channel contract before handing realtime work to a frontend developer.

Owner copy workflow:

1. Open Channels in the project dashboard.
2. Select the channel used by the frontend.
3. Copy the path, auth mode, access rules, subscribe message, event payload examples, error payloads, heartbeat interval, pong timeout, close-code behavior, replay policy, and reconnect expectation.
4. Paste those fields into External Frontend Handoff.
5. If any of those fields are unknown, do not ask the frontend developer to infer them from public docs.

Common subscribe message:

{
  "type": "subscribe",
  "channel": "cases"
}

Common data event:

{
  "type": "case.updated",
  "channel": "cases",
  "payload": {
    "id": "case_123",
    "status": "open",
    "updated_at": "2026-07-08T00:00:00.000Z"
  }
}

Common error event:

{
  "type": "error",
  "code": "unauthorized",
  "message": "Invalid token"
}

If the channel implements acknowledgements, presence, replay, or reconnect backoff, include examples in the project handoff. If it does not, the frontend should reconnect with exponential backoff and refetch REST state after reconnect.

Heartbeat, Close Codes, and Reconnects

Realtime behavior is configured per project. Include these fields in generated docs or the frontend handoff when the frontend depends on realtime:

| Field | Example |
| --- | --- |
| Heartbeat | Server sends { "type": "ping" }; client replies { "type": "pong" } |
| Close codes | 1000 normal close, 1008 auth or policy failure, project-specific validation codes |
| Acknowledgement | { "type": "ack", "id": "msg_123" }, if messages require delivery confirmation |
| Replay | Cursor, last event id, timestamp window, or no replay |
| Reconnect | Exponential backoff such as 1s, 2s, 5s, 10s, then max 30s |

If replay is not implemented, clients should refetch REST state after reconnect. Mobile clients should also refetch after app resume because the socket may have been suspended.

Include the exact heartbeat interval and timeout in project docs when realtime is part of the frontend contract. For example: server ping every 25 seconds, client pong within 10 seconds, close with 1008 when auth expires, reconnect with exponential backoff up to 30 seconds, then refetch REST state after reconnect.

Use Cases

| Use Case | Channel Messages |
|---|---|
| Live chat | Broadcast chat messages to room participants |
| Notifications | Send targeted messages to specific users |
| Live dashboard | Push metric updates to all connected dashboard clients |
| Collaborative editing | Broadcast document changes to all editors |
| Order tracking | Push status updates to the customer watching their order |
| Multiplayer games | Sync game state across connected players |

Connection Management

Spala tracks all active WebSocket connections and provides monitoring through the dashboard. You can see the number of connected clients, connection duration, and message throughput. If a client connection drops unexpectedly, the On Disconnect handler fires automatically to clean up.

A descriptive name for the channel
The WebSocket endpoint path (e.g., /ws or /ws/chat)
Required auth method: None, JWT, or API Key
Function that runs when a client connects
Function that runs when a client disconnects
Function that runs when a message is received from a client
Maximum simultaneous connections allowed
REST Channels
/channels/rest-channels
Group REST endpoints with shared configuration
Channels Overview
/channels
Learn about all channel types in Spala
External Frontend Handoff
/guides/frontend-handoff
Copy realtime contract details for frontend builders
Build Realtime Chat
/guides/realtime-chat
Step-by-step guide to building a chat feature