# Multiple rooms

> Run several rooms in one Node process.

You don't need a separate program for each room. One Node process can run
several rooms side by side, for example one per game mode. Each room is
independent: it has its own identity from the Creator Portal, its own engine
threads and its own queue of events, so a busy room doesn't slow down the
others.

```js title="rooms.js"
import { Room } from "@disko-game/room";

/**
 * A room identity from the dashboard, from `<prefix>_ID` and `<prefix>_TOKEN`.
 * @param {string} prefix
 */
function identity(prefix) {
  const id = process.env[`${prefix}_ID`];
  const token = process.env[`${prefix}_TOKEN`];

  if (!id || !token) {
    throw new Error(`Set ${prefix}_ID and ${prefix}_TOKEN from the dashboard`);
  }

  return { id, token };
}

// One Node process can run any number of rooms. Without `listen`, each room
// takes the next free UDP port from 4433 up to 4532.
const rooms = await Promise.all(
  [
    { ...identity("ROOM_A"), name: "Arena 1" },
    { ...identity("ROOM_B"), name: "Arena 2" },
  ].map((room) => Room.launch({ ...room, game: "gabriel/arena@1.4.2" })),
);

for (const room of rooms) {
  console.log(`${room.name}: ${room.url}`);
}

process.on("SIGTERM", () => {
  void Promise.all(rooms.map((room) => room.close()));
});
```

Things to know when running several rooms:

- Without `listen`, each room takes the next free UDP port from 4433 up to 4532.
- A native engine failure closes only the affected room, with the `close`
  reason `"engine_error"`.
- A Node crash ends every room in the process, so keep handlers robust.
- Events wait for the main thread in a bounded queue (`limits.eventQueue`,
  4096 per room). When it is full, new chat gets a retryable busy response,
  and if any other event cannot be queued the room closes with
  `"controller_overloaded"`.
- Group rooms in the Creator Portal to organize them; groups do not affect
  hosting.
