Skip to main content

State (Room State)

Beta

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

room.state is the authoritative core of Room.

Clients do not mutate room state directly. They send actions, the server validates them in handlers.actions, and the runtime syncs only the changed fields back to clients.

Three State Areas

AreaWho can read itWho can write itGood for
sharedStateEveryone in the roomServer onlyBoard state, score, phase, shared counters
playerStateThe owning player onlyServer onlyHP, private hand, inventory, personal cooldowns
serverStateServer onlyServer onlyRNG seeds, anti-cheat data, internal caches

Client Surface

Assume room is an authenticated room client created with client.room(...).

const shared = room.state.getShared();
const mine = room.state.getMine();

room.state.onSharedChange((state) => renderBoard(state));
await room.state.send('MOVE', { x: 5, y: 3 });

Server Surface

room.state.send(...) maps to handlers.actions on the server.

rooms: {
game: {
state: {
actions: {
MOVE: (payload, room, sender) => {
room.setPlayerState(sender.userId, (state) => ({
...state,
position: { x: payload.x, y: payload.y },
}));
return { ok: true };
},
},
},
},
}

The main server APIs are:

  • room.getSharedState() / room.setSharedState(...)
  • room.player(userId) / room.players()
  • room.setPlayerState(userId, ...)
  • room.getServerState() / room.setServerState(...)
  • room.saveState()

State vs Other Room Capabilities

  • Use Members for presence and lightweight ephemeral member state.
  • Use Signals for fire-and-forget events that should not become source of truth.
  • Use Meta for lobby-safe information that can be fetched before join.

Hooks and Persistence

  • hooks.state.onStateChange(delta, room, ctx) lets you mirror or observe authoritative changes.
  • room.saveState() forces immediate persistence for critical updates.
  • State survives hibernation according to stateSaveInterval and stateTTL. See Advanced.