Skip to main content
This page covers the current version of Realtime. For the original channel triggers — a single trigger per channel handling join and message — see Realtime Triggers (Legacy).
Realtime triggers require a paid instance.
Triggers are function stacks that run at the boundaries of a client’s lifecycle. They come in two declarations, one per scope, and each selects which events it handles through an actions map.

Server scope

realtime_server_trigger runs for the connection itself, regardless of which channels the client later joins.
XanoScript

Connect

Runs when a client attempts to open a connection to the realtime server. A connect trigger is gating — it can veto the entire connection. This is the right place for checks that apply to the whole server: is this account active, is this token still valid, is this client plan-eligible.

Disconnect

Runs when a client’s connection ends. Observational — it can’t reject anything. Use it for cleanup: releasing a claim, marking a user offline, or writing a session record.

Channel scope

channel_trigger runs for a specific channel.
XanoScript

Join

Runs when a client attempts to join the channel, before the join takes effect. A join trigger is gating — it can veto the join. This is where you authorize against your own data: take the room from the channel path, check it against a membership table, and reject anyone who isn’t a member.

Leave

Runs when a client leaves the channel. Observational. The counterpart to join: update presence records, release a lock, or log the session.

Deliver

Runs once per recipient, as a message is delivered. A deliver trigger can rewrite that copy or drop it entirely. This is what turns one publish into N personalized deliveries. From a single message you can:
  • Redact — strip fields a particular recipient isn’t cleared to see
  • Personalize — localize, or add recipient-specific context
  • Drop — suppress delivery to a recipient who has muted or blocked the sender
Each recipient’s trigger run is independent, so one recipient being dropped has no effect on the others.
A deliver trigger runs for every recipient of every delivery, so its cost scales with fan-out. Keep it lean — prefer data you already have on hand over a database query per recipient on a channel with many listeners.

Summary

Declaration clauses

As with every trigger type in Xano, the input block is predefined by the system — it’s provided automatically and isn’t yours to modify. Open a trigger in the builder to see the fields available for the events it handles.

Complete join authorization example

This example assumes the chat server from Servers & Channels exists. Create each declaration in its own file. First, create a channel whose join decision will be made by the trigger:
XanoScript
Then create its join trigger. This uses the system input schema returned by a workspace pull:
XanoScript
An anonymous client is refused with Sign in to join members; a client connected with a valid application user JWT is admitted. Pass the JWT as the WebSocket subprotocol. Return a real boolean in allowed. This example checks authentication only. For room membership or tenant isolation, replace the decision with authorization against your own application data. A matching channel path alone is not an access check. The platform normalizes the trigger inputs on import. Keep the schema returned by pull instead of adding custom fields. realtime.get_session supplies the current connection context; its params can contain string path values, as described in Typed path parameters.

Next steps

Access Control

How triggers fit with channel and message settings.

Messages

Delivery targeting and guarantees.