Skip to content

Realtime

Truss provides realtime subscriptions using PostgreSQL’s LISTEN/NOTIFY mechanism and WebSocket connections. Subscribe to table changes and receive events instantly.

How it works

  1. You create a subscription for a table (e.g., public.messages)
  2. Truss creates a PostgreSQL trigger on that table
  3. On INSERT, UPDATE, or DELETE, the trigger sends a NOTIFY to a channel
  4. Truss’s dedicated LISTEN connection picks up the notification
  5. The event is broadcast to all connected WebSocket clients

Setup

No additional services required — realtime works with just PostgreSQL. The WebSocket server is built into the Truss API.

Subscribing via dashboard

Navigate to Realtime in the sidebar. You’ll see:

  • Active subscriptions and their status
  • A live event log (last 200 events)
  • Controls to subscribe/unsubscribe from tables

Subscribing via API

Create a subscription

Terminal window
curl -X POST http://localhost:8787/api/realtime/subscribe \
-H "Content-Type: application/json" \
-d '{
"schema": "public",
"table": "messages"
}'

This creates a trigger on public.messages that fires on INSERT, UPDATE, and DELETE.

Remove a subscription

Terminal window
curl -X DELETE http://localhost:8787/api/realtime/subscribe \
-H "Content-Type: application/json" \
-d '{
"schema": "public",
"table": "messages"
}'

List subscriptions

Terminal window
curl http://localhost:8787/api/realtime/subscriptions

Check status

Terminal window
curl http://localhost:8787/api/realtime/status

Returns the listener connection status, active channels, connected WebSocket clients, and event log size.

Connecting via WebSocket

Connect to the WebSocket endpoint at /realtime:

const ws = new WebSocket('ws://localhost:8787/realtime');
ws.onopen = () => {
console.log('Connected to Truss realtime');
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Event:', data);
// {
// schema: "public",
// table: "messages",
// operation: "INSERT",
// row: { id: 1, text: "Hello", created_at: "..." },
// old_row: null,
// timestamp: "2025-01-15T10:00:00Z"
// }
};
ws.onclose = () => {
console.log('Disconnected — will auto-reconnect');
};

Event format

Each event contains:

  • schema — the table’s schema (usually public)
  • table — the table name
  • operationINSERT, UPDATE, or DELETE
  • row — the new row data (null for DELETE)
  • old_row — the previous row data (for UPDATE and DELETE)
  • timestamp — when the event occurred

Event log

Truss keeps the last 200 events in memory. Fetch them via:

Terminal window
curl http://localhost:8787/api/realtime/events

Clear the log:

Terminal window
curl -X POST http://localhost:8787/api/realtime/clear-log

Available tables

List tables eligible for realtime subscriptions:

Terminal window
curl http://localhost:8787/api/realtime/tables

Architecture notes

  • The LISTEN connection is a dedicated pg.Client (separate from the connection pool)
  • It auto-reconnects on errors
  • Triggers are named truss_rt_{schema}_{table} and send to matching channels
  • Subscriptions are persisted in truss_internal.realtime_subscriptions
  • Webhook triggers can also fire on realtime events (see Webhooks)