Realtime
Push live data to one user or a room over SSE/WebSocket - model subscriptions, presence, room gating, and a Redis backplane. Full guides live in the Realtime section.
Realtime
umbral-realtime pushes data to one user or a named room without hand-rolling connection bookkeeping. It ships two transports - Server-Sent Events (push-only) and WebSocket (bidirectional) - over one connection registry, plus a GroupPolicy auth seam, live model-change fan-out, presence, and a Redis backplane for horizontal scale.
use umbral_realtime::Realtime; // Fire-and-forget; no-ops when RealtimePlugin isn't installed.Realtime::to_user("42").send("notification", &payload).await; // the user's PK as a stringRealtime::to_group("public:lobby").send("message", &msg).await;// One <script src="/realtime/client.js">, then - one shared connection across every tab:umbral.realtime.subscribe("public:lobby", { message: (m) => render(m) });This is the plugin overview. The full guides - setup, room gating, model subscriptions, presence, transports, and scaling - live in the dedicated Realtime section.
The guides
Getting started
Install RealtimePlugin, wire identity, add the client script, and send your first event end-to-end.
Gating rooms
GroupPolicy + group_policy_fn - who may join which room. public:* is open by default; everything else is denied.
Model subscriptions
expose::<T>() pushes live model changes through a field whitelist (id-only by default). Subscribe with umbral.realtime.model(...).
Presence
Who's online in a room - opt-in per group, identity projected to id-only by default, deduped by user.
Transports
SSE vs WebSocket, the one-connection-per-browser SharedWorker model, and Last-Event-ID reconnect replay.
Scaling
A Redis backplane for multi-instance dispatch - proven non-starving to 10k connections.
At a glance
- Two transports - SSE (push-only, auto-reconnect) and WebSocket (bidirectional):
GET /realtime/sse,GET /realtime/ws(remount all four routes under any base withRealtimePlugin::new().at("/rt")). - Safe by default - anonymous connections may join only
public:*rooms; model exposure and presence are opt-in, exposed model fields are whitelisted, and a built-in Origin guard rejects cross-origin WebSocket upgrades (CSWSH) in prod with no config. See Gating rooms and Transports. - One connection per browser - a
SharedWorkershares a single SSE stream across all tabs and subscriptions, so opening many tabs never exhausts the browser's HTTP/1.1 connection limit. - Fire-and-forget sends -
Realtime::to_user / to_group / broadcastpublish without blocking on socket I/O and no-op when the plugin isn't installed, so a handler can call them unconditionally (Realtime::is_installed()if you need to check).
See also
- The full Realtime section for setup, gating, model subscriptions, presence, transports, and scaling.
- The Plugin trait - how
RealtimePlugin(and every plugin) plugs in.