Hibernation

irtio saves an idle room’s state and stops its simulation. A join, incoming client frame, or durable alarm wakes it with that state restored.

Configure idle time

ModeHibernates after idleMs with
eventNo incoming frames, even if clients are connected
tickNo connected clients

idleMs defaults to 30000 milliseconds. Set it to 0 to keep the room awake. Event rooms can also call room.sleep() to request hibernation immediately.

// Options in irtio/room.ts
mode: 'event',
idleMs: 60_000,

When a project’s server goes idle, its rooms sleep together. In a project with multiple servers, each server sleeps and wakes independently.

Keep durable values in state

Schema state survives hibernation, including field values, owners, and collection insertion order. The tick count and seeded random stream resume. Physics restoration depends on the engine: Rapier restores its world snapshot; Matter rebuilds from saved body state.

ValueAfter a wake
Schema stateRestored
Player storageRemains available independently of the room
Durable alarmsRemain scheduled; overdue alarms run after wake
Module variables and closuresReinitialized
room.setTimeoutCallback cancelled, but the room is woken at the due time; catch up in onWake against a deadline kept in state
room.setIntervalCallback cancelled, and no wake: a cadence is not a deadline. Re-arm it in onWake, or use a durable alarm to fire while the room sleeps
In-flight promisesReject with room is hibernating
PresenceRebuilt from attached clients

A room that hibernates while holding a room.setInterval logs a warning naming both ways out, so a dropped interval is never silent. Use durable alarms for deadlines that must survive sleep. Use room.now for elapsed-time decisions; the tick count measures simulation time and pauses during hibernation. room.now starts again when a room wakes, so it measures time within one sitting. A deadline stored in state across a sleep is wall clock: Date.now() + ms.

Lifecycle callbacks

onSleep(state, room) runs before state is saved. onWake(state, room) runs after restoration and before clients rejoin. onCreate runs only when the room is first created.

A resumed client runs onJoin again with ctx.reconnecting === true. Keep the guard when spawning players:

onJoin(state, ctx) {
  if (ctx.reconnecting) return;
  state.players.add(ctx.clientId, { x: 0, y: 0 }, { owner: ctx.clientId });
},

This excerpt assumes a player schema with x and y fields. If saving fails, the room stays awake.

Respawn NPCs after waking

Hibernation stops clients created by room.spawnNPC without running onLeave. Their rows remain in the saved state, but their sessions are not restored.

In onWake, remove stale player rows before spawning replacement NPCs. This excerpt assumes each row in state.players uses its owner’s client id as its key:

onWake(state, room) {
  const present = new Set(room.clients.map((c) => c.clientId));
  for (const [id] of state.players) {
    if (present.has(id)) continue;
    // Restore any items this player held before removing the row.
    state.players.remove(id);
  }
  // Call room.spawnNPC here for each replacement NPC.
}

Each replacement NPC receives a new client id. Create its row with that id as the owner. See NPCs for a spawn example.

What players see

A fresh join waits for the room to start. Show a connecting state using the client status API.

Clients whose sockets stayed open receive a fresh snapshot without a status change. A client whose reconnect grace expired is removed before queued input is processed. Handle reconnection through the normal lifecycle rather than treating a wake as a new match.

A room can wake on a different server than the one it slept on, for example when its server stops answering. It is the same wake and it reads the same save, so the room loses only what happened after that save, as it would after any other server failure. See placement.

Retention

Sleeping state is kept indefinitely unless the room type declares retention. Expiration deletes its snapshots, saves, and alarms while leaving player storage and leaderboards intact. It is checked every 15 minutes after the requested duration; active rooms, pending restores, and future alarms protect a room from expiry. See room types.

Test a wake

Room tests record sleep requests but do not serialize and restart the room. To verify persistence, run against irtio dev, let the room idle, then rejoin and check the restored state.