Multiplayer Framework
Free and Open-source. Built on Node.js.
Supports your favorite engine & platform
- Server-authoritative
- Room-based system
- State synchronization
- Match-making API
- Scale horizontally or vertically
- JavaScript/Node.js ecosystem
- MIT License
Architecture / Stack
A solid stack so you can focus on your game instead of re-inventing the wheel.
Node.js Runtime
Node.js is an asynchronous event-driven JavaScript runtime, designed to build scalable network applications.
Learn about Node.jsNetworking Transport
WebSockets is used as transport layer. Documentation
Support for WebTransport is in our public roadmap.
Room-based system
On-demand, stateful rooms are spawned per client request.
See moreMessage Serialization
For state sync, we use our own binary delta serializer. For every other message, we use the fastest MessagePack serializer available for JavaScript.
Web / API Routes
Define your own custom API routes via Express or µWebSockets.js
See moreDatabase / Storage / Authentication
Bring your favorite Node.js tool here. You are free to choose which database or authentication provider to use.
(An official recommendation is coming soon).
Rooms & Match-making
Let clients spawn and join into multiple rooms.
Server-side
Write your server room code:
import { Room } from "colyseus";
class MyRoom extends Room { maxClients = 4; onCreate(options) {/* your code */} onAuth(client, options) {/* your code */} onJoin(client, options) {/* your code */} onLeave(client) {/* your code */} onDispose() {/* your code */}}
Expose the room for match-making:
// ...gameServer.define("my_room", MyRoom);
Client-side
Let the client join the room. If no room has been found, the server will create one.
import { Client } from "colyseus.js";
// Initialize SDKconst client = new Client("https://0.0.0.0:2567");
// Connect to a roomconst room = await client.joinOrCreate("my_room");
State Synchronization
An unique approach to room state synchronization.
Server-side
Define your synchronizable state structures
import { type, Schema, MapSchema, ArraySchema } from "@colyseus/schema";
export class Player extends Schema { @type("string") name: string; @type("number") position: number;}
export class MyState extends Schema { @type({map: Player}) players = new MapSchema<Player>(); @type(["number"]) board = new ArraySchema<number>([0, 0, 0, 0, 0, 0, 0, 0, 0]); @type("string") currentTurn: string;}
Mutate the state on within your room code:
import { Room } from "colyseus";import { MyState } from "./MyState";
export class MyRoom extends Room<MyState> { state = new MyState();
onCreate() { // room has been created }
onJoin(client, options) { // new client joined the room this.state.players.set(client.sessionId, new Player()); this.state.currentTurn = client.sessionId; }
onLeave() { // client left the room this.state.players.delete(client.sessionId); }}
Client-side
Listen to the changes coming from the server:
import { Client, getStateCallbacks } from "colyseus.js";// (...)
const client = new Client("https://0.0.0.0:2567");const room = await client.joinOrCreate("my_room", { /* client options */});
const $ = getStateCallbacks(room);
// on player added/join$(room.state).players.onAdd((player, sessionId) => { console.log("Player added!", player, sessionId); // on player "position" change player.listen("position", (position, previousPosition) => { console.log("player position changed!", { position, previousPosition }); });});
// on player removed/left$(room.state).players.onRemove((player, sessionId) => { console.log("Player removed!", player, sessionId);});
// on "board" change$(room.state.board).onChange((value, index) => { console.log("board item changed to", value, "at", index);});
// on "currentTurn" change$(room.state).listen("currentTurn", (currentTurn, previousValue) => { console.log("currentTurn:", currentTurn); console.log("currentPlayer:", room.state.players.get(currentTurn));});
Scalability
Simple yet powerful scaling strategy
- Distribute rooms across servers and/or processes
- Allow cluster-wide match-making
- Leverage all your available CPUs
- Connect clients directly to their requested rooms
- Stateful processes keep track of their own rooms

Tooling
Built-in tools that accompany you from development to production.
Client-side Playground
Easily create client connections and inspect how they are exchanging data with the server
Read documentationRealtime Room Inspector
View and inspect the list of rooms spawned by the server.
Read documentationUnit Testing
Utility methods for testing your rooms with your favorite testing framework
Read documentationLoad Testing
Evaluate how your server behaves under high traffic.
Read documentationNode.js ecosystem
Bring your favorite tools to your Colyseus server.
Become a Sponsor
The sustainability of Colyseus relies on Colyseus Cloud subscriptions and sponsorships.
If you benefit from the project but are not yet using Colyseus Cloud, please consider sponsoring it.