Platform

Realtime

Subscribe to database changes over WebSockets. Stream INSERTs, UPDATEs, and DELETEs in real time with column-level filters, broadcast channels, and presence tracking.

The Realtime module pushes database changes to connected clients the instant they happen. No polling, no manual refresh — your UI stays in sync with your data automatically.

How it works

Every OrbitNest project includes a WebSocket endpoint at /realtime/v1/ws. Clients authenticate with a JWT (passed as a query parameter or header), then subscribe to one or more channels. The server pushes events as they occur.

Subscription types

Table subscriptions

Subscribe to table:schema.table_name channels to receive row-level change events. Each event includes the event type (INSERT, UPDATE, DELETE), the new row data, and the old row data (for updates and deletes).

typescript
import { createClient } from 'orbitnest-node';

const client = createClient({
  projectUrl: process.env.ORBITNEST_URL!,
  anonKey:    process.env.ORBITNEST_ANON_KEY!,
});

// Subscribe to all changes on the "messages" table
const subscription = client.realtime
  .channel('table:public.messages')
  .on('INSERT', (payload) => {
    console.log('New message:', payload.new);
  })
  .on('UPDATE', (payload) => {
    console.log('Updated:', payload.new);
  })
  .on('DELETE', (payload) => {
    console.log('Deleted:', payload.old);
  })
  .subscribe();

Column-level filters

Narrow subscriptions to specific rows using PostgreSQL-style filters. Supported operators: eq, neq, in, gt, lt, gte, lte, and like.

typescript
// Only receive messages for a specific chat room
client.realtime
  .channel('table:public.messages')
  .on('INSERT', (payload) => {
    console.log('New message in room:', payload.new);
  }, { filter: { column: 'room_id', op: 'eq', value: 'room-42' } })
  .subscribe();

Broadcast channels

Broadcast channels (broadcast:channel_name) let you send custom application-level messages between connected clients without touching the database. Great for typing indicators, cursor positions, or game state.

typescript
// Send a broadcast event
client.realtime
  .channel('broadcast:typing')
  .send({ type: 'typing', payload: { user: 'ali', room: 'general' } });

// Receive broadcast events
client.realtime
  .channel('broadcast:typing')
  .on('typing', (payload) => {
    console.log(payload.user, 'is typing...');
  })
  .subscribe();

Presence tracking

Track which users are currently online on a channel. The server maintains presence state and pushes join/leave events automatically.

Rate limits & connection limits

  • Up to 100 subscriptions per WebSocket connection.
  • Token-bucket rate limiting: 60 burst, 30/sec refill.
  • Heartbeat interval: 30 seconds — missed heartbeats close the connection.

Enabling realtime on tables

By default, tables do not broadcast change events. Enable realtime per table from the Studio UI (Tables → Realtime toggle) or via the REST API:

bash
# Enable realtime on the "messages" table
curl -X POST \
  https://studio.orbitnest.io/api/projects/your-slug/realtime/tables \
  -H "Authorization: Bearer $TOKEN" \
  -d '{ "table": "messages", "schema": "public", "enabled": true }'

Server-side broadcast

Edge functions and backend services can broadcast events using the REST endpoint — no WebSocket connection required:

typescript
// Inside an edge function
await fetch(`${PROJECT_URL}/realtime/broadcast`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${SERVICE_ROLE_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    channel: 'notifications',
    event: 'new_order',
    payload: { orderId: '12345', total: 29.99 },
  }),
});

Flutter SDK

The Flutter SDK includes a RealtimeChannel class with the same subscribe/filter/broadcast API. See the Flutter SDK docs for platform-specific examples.