Multiplayer Framework

Free and Open-source. Built on Node.js.

npm create colyseus-app@latest ./my-server

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.js

Networking 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 more

Message 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 more

Database / 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:

MyRoom.ts
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:

app.config.ts
// ...
gameServer.define("my_room", MyRoom);

Client-side

Let the client join the room. If no room has been found, the server will create one.

client.ts
import { Client } from "colyseus.js";
// Initialize SDK
const client = new Client("https://0.0.0.0:2567");
// Connect to a room
const room = await client.joinOrCreate("my_room");

State Synchronization

An unique approach to room state synchronization.

Automatically synchronized
Delta compressed
Client-side callbacks
Optimized for speed & bandwidth

Server-side

Define your synchronizable state structures

MyState.ts
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:

MyRoom.ts
import { Room } from "colyseus";
import { MyState } from "./MyState";
export class MyRoom extends Room<MyState> {
onCreate() {
// Room has been created
this.setState(new MyState());
}
onJoin(client, options) {
// A client joined the room
this.state.players.set(client.sessionId, new Player());
this.state.currentTurn = client.sessionId;
}
onLeave() {
// A client left the room
this.state.players.delete(client.sessionId);
}
}

Client-side

Listen to the changes coming from the server:

client.ts
import { Client } from "colyseus.js";
// (...)
const client = new Client("https://0.0.0.0:2567");
const room = await client.joinOrCreate("my_room", {
/* client options */
});
// 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
Scalability

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 documentation

Realtime Room Inspector

View and inspect the list of rooms spawned by the server.

Read documentation

Unit Testing

Utility methods for testing your rooms with your favorite testing framework

Read documentation

Load Testing

Evaluate how your server behaves under high traffic.

Read documentation

Node.js ecosystem

Bring your favorite tools to your Colyseus server.

Prisma PostgreSQL MongoDB Discord.js Thirdweb Moralis PassportJS Firebase PlayFab
Colyseus Sponsors

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.