irt.io vs Colyseus
Colyseus is an open source multiplayer framework for Node.js. You write rooms, clients send messages, and the server mutates state that syncs to everyone as binary patches. The structural difference is that you operate a Colyseus server, and irtio operates yours.
When Colyseus is the better choice
- You want to own the runtime. Colyseus is open source. You can read it, patch it, run it on your own machines, and keep it running after any vendor goes away. irtio is a hosted service, and there is no version of it you run yourself.
- Your client is not a browser. Colyseus has client SDKs for engines outside the web, including Unity and C#. irtio clients are TypeScript in a browser.
- Your room needs to talk to other services. A Colyseus room is ordinary Node code, so it can
query a database, call an API, and await anything. An irtio room handler is synchronous and has
no
fetch, nofsand noasync, which is the price of replayable rooms. - You already run Node services. Multiplayer becomes another service in a deployment you already understand.
When irt.io is the better choice
- You do not want to operate a game server.
irtio deployships a room file. There is no Dockerfile, no process to keep alive, no scaling decision, and no capacity planning. - Clients should write their own state. In irtio each instance has an owner, and the owner assigns to it like a local object. A validator on the server accepts, clamps or rejects the write before anyone else sees it. Nothing has to be routed through a message handler first.
- You want the game-shaped layers. Physics, client prediction, voice and simulated players are part of irtio rather than parts you assemble.
- An idle game should cost nothing. irtio rooms hibernate and wake with their state intact.
Model comparison
| Colyseus | irt.io | |
|---|---|---|
| Authority | Server | Server |
| Who operates the server | You, or their hosting service | irtio |
| State model | Server mutates room state, clients send messages | Typed schema, per-instance ownership, binary deltas |
| Prediction | You write it | Built in for physics rooms, interpolation for everything else |
| Physics | Bring your own | Rapier in 3D or 2D (or matter.js), stepped on the server |
| Voice | Not included | joinVoice(room) |
| Testing | Test helpers you run against a booted server | In-process rooms on a fake clock, plus simulated players over real sockets |
| Hibernation and idle cost | The process runs whether or not anyone is playing | Rooms sleep after idleMs and wake with state intact |
| Language | TypeScript server, clients for several engines | TypeScript, browser clients |
What porting looks like
The two projects agree on the important thing, so most of a port is renaming rather than
redesigning. Your state definition becomes a schema that both halves of the game import. Your room class becomes a room file with onJoin, onLeave and a tick.
The one decision that is not mechanical is what happens to your message handlers. Each one goes to
a rung on the ladder. A handler that only records what a player did
with their own avatar becomes an owned write plus a validator, and the message disappears. A handler that decides an
outcome becomes an RPC over a server-owned collection, which is close to a
one-to-one translation. Anything you drive from a simulation interval becomes the room’s tick.
Two things need real work. Room code that awaits a database or an API has to move out of the room, because handlers are synchronous. And matchmaking changes shape: a room code covers party games, and quick match covers the queue.
Migrating from Colyseus walks the whole path with code on both sides.
Next steps
- The mental model for ownership and the ladder.
- Server authority and validation for validators and the tick.
- Migrating from Colyseus for the port itself.
- Deploying a room for what replaces your deployment.
This page describes each product’s model as it stood at the page’s last review. Send corrections to hello@irt.io.