Deploying a room

Deploy your room from the project root. irtio builds the server code, checks schema compatibility, and hosts the room. Deploy the matching browser bundle after the room is ready.

Sign in

npx irtio login

Finish sign-in in the browser. The CLI saves the credential for later commands. For automation and credential locations, see CLI login.

The command

npx irtio deploy

Run it from the project root, next to irtio.json.

Verify the deployment

The command builds your room, checks its schema, uploads the bundle, and prints the deployment version. A rejected deployment prints the reason and exits non-zero. Keep the client and room on compatible schemas; schema changes explains which edits require a migration.

If your project runs on more than one server, the deploy reaches every running server one after another and waits for each to confirm before moving to the next. A deploy that some servers refuse is reported rather than left half-applied: the CLI names the server that refused and lists the others’ outcomes. Run the same command again to retry; each server is checked against the version it already has, so only the ones still needing the deploy are touched.

Import only the physics engine your client uses. See client physics setup.

Ship the client with the room

irtio deploy --static dist/, or a static key in irtio.json, uploads your built client alongside the room. The page carries a copy of your schema, so a page built before your last schema edit cannot join the room this deploy ships: every join fails with E_SCHEMA_MISMATCH while your local checks all pass.

End your client build with irtio stamp to catch that:

// package.json
"scripts": {
  "build": "vite build && irtio stamp dist"
}

The stamp records which schema the build was made against, and the deploy refuses a page whose stamp does not match the schema it is shipping. Without a stamp, the deploy can only compare file dates, and it warns rather than refuses.

One project puts one site live at a time. If two irtio deploy --static runs for the same project reach that step together, for example two CI jobs, the second fails with 409 E_CONFLICT without putting its own files live. Run it again once the first has finished.

Deploy a relay schema

Run irtio deploy with irtio/schema.ts and no room file to deploy a relay room. Clients can use typed messages and declared shared state. A changed relay schema resets stored room state and reconnects clients; deploying the same schema preserves it.

Flags

FlagWhat it does
--room <file>Use this room file instead of searching for one
--project <id>Deploy to this project id, ignoring irtio.json and the schema
--allow-breakingShip a breaking schema change, but only if a matching migration file exists. Changes confined to the RPC and message tables are the exception: no snapshot is affected, so no migration is needed
--url <control>Use a specific irtio URL instead of the one you signed in to
--strategy drain\|migrateWhat happens to rooms already running. drain (default) leaves them on their old version. migrate moves them onto the new version now. See strategies below

deploy asks at most two questions, and only when they apply: the name for a project that does not exist yet, and the production origin on a first deploy. Both accept an empty line. For a deploy with no prompts at all, pass --project for a project that already exists.

Versions

Each deployment gets an increasing version number. New rooms use the latest version. Sleeping rooms upgrade when they wake; running rooms follow the selected deployment strategy.

Deployment strategy

StrategyRunning roomsConnected clients
drain (default)Finish on their current versionContinue playing
migrateSave, restart, and migrate one room at a timeBrief resync for compatible changes; reload required for breaking changes
npx irtio deploy --strategy migrate

Under migrate, a breaking schema change closes clients with E_SCHEMA_MISMATCH. Compatible code or additive changes resync on the same socket. Pending predictions are discarded during resync. Sleeping rooms update at their next wake under either strategy.

Review the CLI’s schema diff before deploying. Appending defaulted or optional fields can be additive; changing sorted collection positions or RPC signatures can be breaking. See schema changes.

Allowed origins

Your project id is public. It ships inside your client bundle, because that is what the client sends when it joins. The allowed-origins list is what stops another site from pointing its own client at your project.

The list starts empty, and an empty list accepts only localhost. Everything else has to be on the list, matched exactly on scheme, host and port.

Two entries you never have to add:

  • localhost is always allowed, on any port and any scheme, whatever else the list says. A dev server pointed at your deployed project works with no setup.
  • A site you publish with irtio deploy --static adds its own origin when it activates. The command prints the origin it registered.

So the list is for the places you host your game yourself: your own domain, an itch.io page, an embed. If your game is served from somewhere you cannot predict, add *, which accepts every origin and is the only wildcard the list understands. If your page is on a host shared with other games, such as a portal, read shared origins before using identity: true.

The dashboard’s API keys page edits the list with a form. There is no irtio origins command, so from a script use the control API:

RequestWhat it does
GET /v1/projects/:id/originsList the allowed origins
POST /v1/projects/:id/origins with body { "origin": "https://mygame.example" }Add one
DELETE /v1/projects/:id/origins?origin=https://mygame.exampleRemove one

Two details matter. A connection that sends no Origin header at all is allowed, because origin locking is a browser-side protection and bots, native clients and irtio simulate have no origin to send. And partial wildcards are not supported: https://*.mygame.example is treated as a literal string and will never match. Only the bare * is a wildcard.

Changes take effect within about 30 seconds. You do not have to redeploy or restart anything.

Checking that a deploy landed

npx irtio rooms          # which rooms exist, their status, when they were last seen
npx irtio logs --follow  # the project's log stream, live

The dashboard’s Deployments page lists every version with its change summary and marks the newest one live. GET /v1/projects/:id/deployments returns the same rows.

Going back to older code

Two different tools do this, and they are not interchangeable.

Deploying old code again as a fresh deploy makes it the next version, moving forward like any other deploy. Treat it like any other deploy: it is a fresh schema diff, so going from v3 back to v2’s schema can itself be a breaking change (a field v3 added is a field this deploy removes) and needs a migration of its own.

irtio rollback <version> is the other tool, and it is what you want after a bad --strategy migrate deploy. It re-promotes an older version directly, creating no new version number, and restores any room that migrated past it to its pre-migration state, discarding what those rooms wrote since. It is a correctness tool for a bad deploy, not a general undo button, and it does not touch your deployed client bundle. See the CLI reference’s irtio rollback for the full behavior, including the client-side gotcha after rolling back a schema change.

On a project running on more than one server, a rollback stops every one of them, not only the one that took the bad deploy: every room’s state is discarded on the next start, per server, the same as it is for one.

A rollback moves the whole project, including every room type it defines. There is no way to roll one type back and leave the others where they are: a version is one project, and types that disagreed about which version they were on would be a project whose stored state disagrees with itself.

irtio rooms restore is a different thing again. It puts a room’s saved state back, not your code. See saves and restores.

Taking a project down

Stop the project’s servers before deleting it:

npx irtio restart
npx irtio delete-project <id> --yes

restart preserves saves, and a new join starts the project again. delete-project permanently removes the project and its control-plane records. It refuses with 409 E_PROJECT_IN_USE while an instance is running or starting. See delete-project for recovery when a stop fails or another join restarts the project.