/ Docs

Realtime

Volcano Realtime provides WebSocket-based real-time communication for your applications.

Volcano Realtime provides WebSocket-based real-time communication for your applications. Enable live updates, collaborative features, and instant notifications with minimal setup.

Features

FeatureDescription
BroadcastPub/sub messaging between connected clients
PresenceTrack online users and share state in real-time
Postgres ChangesSubscribe to database INSERT/UPDATE/DELETE events
Per-projectEach project has isolated realtime channels
SDK supportJavaScript/TypeScript SDK with automatic reconnection
SecurityJWT-based authentication with automatic project isolation

Quick example

Connect and subscribe to a channel

import { VolcanoRealtime } from '@volcano.dev/sdk/realtime';

const realtime = new VolcanoRealtime({
  apiUrl: 'https://api.yourapp.com',
  anonKey: 'your-anon-key',        // Contains your project ID
  accessToken: 'user-access-token'
});

// Connect
await realtime.connect();

// Subscribe to a broadcast channel
// Just specify the channel name - project isolation is automatic
const channel = realtime.channel('chat-room-123');

channel.on('message', (payload) => {
  console.log('New message:', payload);
});

await channel.subscribe();

// Send a message
await channel.send({ event: 'message', text: 'Hello, world!' });

Track user presence

// 1. Sign up with metadata (display_name appears in presence)
const { session } = await volcano.auth.signUpAnonymous({
  display_name: 'Alice'
});

// 2. Connect with the session
const realtime = new VolcanoRealtime({
  apiUrl,
  anonKey,
  accessToken: session.access_token
});
await realtime.connect();

// 3. Subscribe to presence
const presenceChannel = realtime.channel('lobby', { type: 'presence' });

presenceChannel.on('presence_sync', () => {
  const state = presenceChannel.getPresenceState();
  const users = Object.values(state).map(info => 
    info.connInfo?.user_metadata?.display_name || 'Anonymous'
  );
  console.log('Online users:', users);
});

presenceChannel.on('join', (info) => {
  const name = info.connInfo?.user_metadata?.display_name;
  console.log('User joined:', name);
});

presenceChannel.on('leave', (info) => {
  console.log('User left');
});

await presenceChannel.subscribe();
await presenceChannel.track(); // Automatic - uses metadata from signup

Subscribe to database changes

A standalone client receives the changed row's primary key. Optional row fetching can add record for INSERT and UPDATE; it does not provide previous row values. See Postgres change payloads.

const dbChannel = realtime.channel('public:messages', { type: 'postgres' });

dbChannel.onPostgresChanges('INSERT', 'public', 'messages', (payload) => {
  console.log('Inserted message ID:', payload.id ?? payload.record?.id);
});

dbChannel.onPostgresChanges('UPDATE', 'public', 'messages', (payload) => {
  console.log('Updated message ID:', payload.id ?? payload.record?.id);
});

await dbChannel.subscribe();

Channel types

Volcano Realtime supports three types of channels:

Broadcast channels (default)

const channel = realtime.channel('room-name');
// or explicitly:
const channel = realtime.channel('room-name', { type: 'broadcast' });

Send and receive messages between all connected clients. Perfect for chat rooms, live updates, and notifications.

Presence channels

const channel = realtime.channel('lobby', { type: 'presence' });

Track which users are online and share state. Great for showing who's online, typing indicators, and collaborative cursors.

Postgres Changes channels

const channel = realtime.channel('schema:table', { type: 'postgres' });

Receive real-time notifications when database rows are inserted, updated, or deleted. Filtered by Row Level Security policies.

Disable Realtime features

Update the project Realtime configuration:

curl -X PUT "$VOLCANO_API_URL/projects/$PROJECT_ID/realtime/config" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"postgres_changes_enabled":false}'
  • Setting postgres_changes_enabled to false closes active connections subscribed to Postgres Changes across all server instances. Broadcast and Presence connections stay open. Volcano removes the project database listeners and generated notification triggers.
  • Setting enabled to false closes all active Realtime connections for the project across all server instances.
  • New connections or subscriptions are rejected while their feature is disabled. Clients can connect again after you enable it.

Project isolation

You never need to specify a project ID. The project is automatically determined from your anon key:

const realtime = new VolcanoRealtime({
  apiUrl: 'https://api.yourapp.com',
  anonKey: 'your-anon-key',         // Contains project_id in JWT claims
  accessToken: 'user-access-token'
});

// These channel names are scoped to your project automatically
const chat = realtime.channel('chat-room');      // Only accessible within your project
const presence = realtime.channel('lobby', { type: 'presence' });

This is consistent with how all other Volcano SDK methods work - the project context comes from your anon key.

Authentication

Volcano Realtime supports multiple authentication methods:

Option 1: User Token (Frontend)

For frontend applications with authenticated users:

const realtime = new VolcanoRealtime({
  apiUrl: 'https://api.yourapp.com',
  anonKey: 'your-anon-key',       // Required: identifies the project
  accessToken: 'user-token',      // Required: authenticates the user
  getToken: async () => {         // Optional: auto-refresh token
    return await refreshAccessToken();
  }
});

Option 2: Service Role Key (Backend)

For backend services, you can use a service role key. The service key contains the project ID, so the anon key is optional:

// Backend - service key only (simplest)
const realtime = new VolcanoRealtime({
  apiUrl: 'https://api.yourapp.com',
  anonKey: '',                    // Not required with service key
  accessToken: 'sk-your-service-key'
});

// Backend - service key with anon key (extra validation)
const realtime = new VolcanoRealtime({
  apiUrl: 'https://api.yourapp.com',
  anonKey: 'your-anon-key',       // Optional: additional validation
  accessToken: 'sk-your-service-key'
});

Note: Service keys bypass Row Level Security for Postgres changes. Use them only in trusted backend environments.

Authentication Summary

ScenarioAnon KeyAccess TokenUse Case
Frontend with userRequiredUser JWTEnd-user applications
Backend serviceOptionalService KeyServer-to-server, bots
Backend with extra validationRequiredService KeyStricter security

Next steps

On this page