Skip to main content
Beta

This feature is in beta. Core behavior is stable, but some APIs or configuration may change before general availability.

Room

JavaScriptDartSwiftKotlinJavaUnityUnrealReact Native

EdgeBase Room is a server-authoritative real-time state synchronization primitive for multiplayer applications. Clients send actions, the server validates and mutates state, and all connected clients receive only the changed parts (deltas) automatically. Ideal for multiplayer games, collaborative editors, live dashboards, voting systems, and auctions — anything where consistency and trust matter.


Control Surface

What is Room?

Room is a real-time state synchronization primitive where the server has full authority over all state changes. Room doesn't just relay messages — it owns the state and enforces the rules.

Room combines five core real-time capabilities in one primitive:

  • room.state (room state) — server-authoritative shared / player / server state with automatic delta sync
  • room.meta (room info) — public-safe room metadata for lobby cards, pre-join summaries, and matchmaking
  • room.members (presence) — built-in presence tracking and ephemeral member state
  • room.signals (broadcast) — lightweight pub/sub for chat, cursors, WebRTC signaling, and other transient events
  • room.media (voice/video) — audio/video/screenshare publish, mute, and device state for conferencing UIs (alpha)

And the client surface includes two companion namespaces around those five capabilities:

  • room.admin — moderation and operator controls such as kick, mute, and role changes
  • room.session — connection lifecycle, reconnect, kicked, and error events

This makes Room ideal for anything where consistency, coordination, or real-time interaction matter:

  • Multiplayer games — lobbies, turn-based, real-time
  • Collaborative editors — shared documents, whiteboards
  • Live dashboards — real-time metrics, leaderboards
  • Voting / polls — tamper-proof state
  • Auctions — server-enforced bidding rules
  • Conferencing — participant tracking, media state, signaling

Choosing Room vs Database Subscriptions vs Push

Choose Room when you need interactive real-time coordination — authoritative state, metadata, presence, signals, or media. If you only need database change feeds in the UI, use Database Subscriptions. If you need delivery to devices outside the active app session, use Push.

For the full comparison, see Choosing Live Features.


How it Works

Action Flow
Client A ── send('INCREMENT') ──▶  Server
                                   │  handlers.actions['INCREMENT'] runs
                                   │  setSharedState(s => ({ ...s, count: s.count + 1 }))
Client A ◀── action_result ─────────│
Client A ◀── shared_delta ──────────│
Client B ◀── shared_delta ──────────│  (auto-broadcast to all)
  1. Client sends an action (type + payload)
  2. Server runs the matching handlers.actions entry
  3. Handler mutates state via setSharedState / setPlayerState / setServerState
  4. Changed fields are automatically broadcast as deltas to connected clients
  5. The handler's return value is sent back to the calling client only

Quick Start

Step 1 — Server: Define a Room

// edgebase.config.ts
import { defineConfig } from '@edgebase/shared';

export default defineConfig({
rooms: {
'counter': {
handlers: {
lifecycle: {
onCreate(room) {
room.setSharedState(() => ({ count: 0 }));
},
},
actions: {
INCREMENT: (_payload, room) => {
room.setSharedState(s => ({ ...s, count: (s.count as number) + 1 }));
return { newCount: room.getSharedState().count };
},
},
},
},
},
});

Step 2 — Clients: Join, Subscribe, Send

Assume client is already initialized with your platform SDK.

const room = client.room('counter', 'room-1');
await room.join();

room.state.onSharedChange((state) => {
console.log('Count:', state.count);
});

const result = await room.state.send('INCREMENT');
console.log(result.newCount);

Step 1's handlers.actions.INCREMENT runs on the server. setSharedState triggers a delta broadcast to all connected clients — including Client B, whose onSharedChange handler fires automatically.


Three State Areas

🌍

sharedState

All clients can read. Server writes only. Game board, scores, shared data.

👤

playerState

Only the owning player can read. Server writes only. HP, inventory, private hand.

🔒

serverState

Server only — never sent to clients. RNG seed, anti-cheat, internal computation.


Client API Overview

Namespace / MethodDescription
room.join() / room.leave()Connect to or leave the room
room.state.*Authoritative actions plus shared / private state reads and subscriptions
room.meta.*Public-safe room metadata, including pre-join fetches
room.members.*Presence list, member join/leave events, and ephemeral member state
room.signals.*Fire-and-forget room events and direct member targeting
room.media.* (alpha)Audio/video/screen publish, mute, device, and track state
room.admin.*Moderation controls such as kick, mute, and role changes
room.session.*Errors, reconnect notifications, kicked events, and connection state

Legacy flat methods such as room.send(...), room.getSharedState(), and room.onMessage(...) remain available for compatibility, but the unified namespace surface is the recommended shape on the newer client SDKs.


Server Lifecycle

HookWhenNotes
handlers.lifecycle.onCreate(room, ctx)First player joins (room created)Initialize shared/server state
handlers.lifecycle.onJoin(sender, room, ctx)Each player joinsInitialize player state. Throw to reject.
handlers.actions[type](payload, room, sender, ctx)Client calls send()Process action, mutate state, return result
handlers.lifecycle.onLeave(sender, room, ctx, reason)Player leavesreason: 'leave' | 'disconnect' | 'kicked'
handlers.lifecycle.onDestroy(room, ctx)Last player leavesPersist final results via ctx.admin.db()

No Other BaaS Has This

Room is not a feature you'll find in Firebase, Supabase, Appwrite, or any other BaaS. Server-authoritative real-time state synchronization has traditionally required a separate multiplayer framework — and a separate server to run it on.

Colyseus / HathoraPartyKit / LiveblocksEdgeBase Room
What it isStandalone game server frameworkCollaboration SDKBuilt-in BaaS feature
Requires separate infra?Yes — dedicated Node.js serversYes — separate deploymentNo — runs inside your EdgeBase project
Auth integrationBuild your ownBuild your ownUses EdgeBase Auth (JWT, access rules)
Database accessSeparate DB neededSeparate DB neededDirect ctx.admin.db() in handlers
Delta syncManual or schema-basedCRDT-basedAutomatic diff-based deltas
3-tier stateNo (single state)NoYes — shared / player / server
CostServer hosting 24/7Per-connection pricingDO duration only — idle = $0

Room gives you a multiplayer backend that shares the same auth, database, and deployment as the rest of your app — no additional infrastructure, no separate billing, no integration glue.


Next Steps