Realtime

Live data without a second backend

Postgres change streams, broadcast and presence over one WebSocket, with the same row-level policies deciding what each subscriber sees.

Realtime product screenshot
realtime
volcano cloud config deployrealtime  enabled · broadcast · presence · postgres_changes✓ wss://…/realtime/v1/websocket ready# then, in the browserchannel.onPostgresChanges('INSERT', 'public', 'cards', render)INSERT public.cards  { id: 'c_18f…', title: 'Ship it' }# subscribers only receive rows their policies already allow
Overview

The usual options are polling or a second system

Either you poll every few seconds and send a thousand queries to find out nothing changed, or you stand up a socket tier, a pub/sub broker and a change-capture pipeline, then keep three deployments and one authorization model in agreement.

Volcano puts change streams, broadcast and presence on the database you already have. Subscribe to a table and its changes start streaming; when the last listener leaves, they stop. Every message is filtered by the same row-level policies that guard a normal query, so the socket needs no permission model of its own.

Transport

One socket, many channels

Channels share the socket, so a screen watching two tables plus a cursor feed and a presence roster still opens one connection. Reconnection, backoff and token refresh belong to the SDK.

  • Hundreds of channels over a single connection
  • Change streams, broadcast and presence on the same socket
  • Reconnects, re-subscribes and refreshes the token for you
one client, five subscriptions
postgres:public:cards        subscribedpostgres:public:comments     subscribedbroadcast:board-42-cursors   subscribedbroadcast:board-42-typing    subscribedpresence:board-42            subscribed · 7 here✓ sockets open: 1
Setup

Subscribing is the whole setup

Subscribe from the client and Volcano starts streaming that table's changes. Nothing is added to your schema, there is no replication to configure, and when the last listener leaves the streaming stops on its own.

  • Streaming begins on the first subscription
  • It stops again when the last listener leaves
  • Subscribe to one event type or all
volcano.dev/dashboard/realtime
Realtime settings with change streams, broadcast and presence enabled
Authorization

The stream obeys your policies

A change event is delivered to a subscriber only if that subscriber could have selected the row. The rule is the row-level policy you already wrote, so there is no second permission model for the socket.

  • Filtered per subscriber, not per channel
  • Anon key plus the user's token to connect
  • Service keys skip policies, so keep them on a server
one UPDATE, two subscribers
# update cards set title = '…' where id = 'c_18f…'ada   (member of the board)   → UPDATE deliveredcleo  (not a member)          → nothingsame policy as select, applied to the stream
Capabilities

What realtime gives you

Postgres change streams

Subscribe to INSERT, UPDATE and DELETE on any table, or to all three at once.

Broadcast

Send a message to everyone on a channel. Nothing is stored, so it suits cursors and typing indicators.

Presence

Track who is on a channel. The full roster is synced to everyone whenever it changes.

Policy-filtered delivery

Each subscriber receives only the rows their row-level policies would return.

One managed WebSocket

Many channels share one connection, with reconnection handled by the SDK.

Turned on in config

Enable broadcast, presence and change streams in volcano-config.yaml and apply with one command.

Code

Connect, subscribe, publish

TypeScript
import { VolcanoRealtime } from '@volcano.dev/sdk/realtime'; const realtime = new VolcanoRealtime({ apiUrl: process.env.NEXT_PUBLIC_VOLCANO_API_URL!, anonKey: process.env.NEXT_PUBLIC_VOLCANO_ANON_KEY!, accessToken: volcano.accessToken, }); await realtime.connect(); const cards = realtime.channel('board-42-cards', { type: 'postgres' }); cards.onPostgresChanges('*', 'public', 'cards', (change) => { // change: { type, schema, table, record, old_record, columns, timestamp } if (change.type === 'DELETE') return removeCard(change.old_record); upsertCard(change.record); }); await cards.subscribe();
Use cases

What people make live

presence on board-42
presence_sync   ada · bob · cleopresence_sync   ada · bob · cleo · danapresence_sync   ada · cleo · dana# bob closed his laptop — no heartbeat code involvedroster maintained by Volcano
Platform

Works with the rest of Volcano

Databases and vector
  • The tables you stream

    Change events come from your own Postgres tables, and the read policy decides who receives each one.

Authentication
  • Who is connected

    Subscribers connect with their session token, so presence and filtering use a real user id.

Functions and agents
  • Progress from a job

    A function can broadcast on a channel while it works, so the page updates without polling.

Next.js frontends
  • Live in the browser

    The realtime client runs in a Next.js client component alongside the rest of the SDK.

Frequently asked questions

Read the docs
Do I have to set up change data capture?

No. Subscribe to a table and Volcano streams its changes from that point on, stopping again once nothing is listening. You do not configure replication, and nothing is added to your schema.

Can a subscriber see rows they are not allowed to read?

No. Change events are filtered per subscriber using the same row-level policies that apply to a normal query, so a user receives an event only if they could have selected that row.

What is the difference between broadcast and postgres changes?

Postgres changes follow writes to your tables and are durable because the row is. Broadcast sends a message to whoever is subscribed right now and stores nothing, which suits cursors and typing indicators.

How many channels can one connection carry?

Hundreds. Channels multiplex over the single socket, so a screen watching two tables plus a cursor feed and a presence roster still holds one connection open. The per-plan ceilings for connections, channels and messages are on the pricing page.

Does a change event include the previous row?

For UPDATE and DELETE, yes. The callback receives record and old_record alongside the event type, schema, table, changed columns and a timestamp, so you can diff the two or remove the row you were given.

How do I turn realtime on?

Set the realtime block in volcano-config.yaml and run volcano cloud config deploy. There is no realtime CLI and nothing to deploy separately.

Ready to make it live?

Build, deploy, and scale on Volcano's global platform — free to start, with no infrastructure to manage.

Checkout more features