Server
The Colyseus Server instance holds the server configuration options, such as transport options, presence, matchmaking driver, etc.
- Transport is the layer for bidirectional communication between server and client.
- Presence is the implementation that enables communication between rooms and/or Node.js processes.
- Driver is the storage driver used for storing and querying rooms during matchmaking.
Overview
The recommended structure to initialize a new Colyseus server is created using npm create colyseus-app@latest command.
npm create colyseus-app@latest ./my-serverYou may add your own Room Definitions, and API routes to your server:
import { defineServer, defineRoom } from "colyseus";
import { MyRoom } from "./rooms/MyRoom";
const server = defineServer({
rooms: {
my_room: defineRoom(MyRoom),
},
express: (app) => {
// Bind your express routes here:
app.get("/", (req, res) => {
res.send("It's time to kick ass and chew bubblegum!");
});
}
});Server Options
Transport (transport)
The Transport Layer is responsible for the networked communication between the server and the client. Colyseus uses TCP/WebSockets for communication by default.
Each Transport has its own options you may customize.
The default transport is WebSocketTransport. See Transport → WebSocket Transport (ws) for more details.
import { defineServer } from "colyseus";
import { WebSocketTransport } from "@colyseus/ws-transport";
const server = defineServer({
transport: new WebSocketTransport({
pingInterval: 10000
}),
});See Transport for more details.
Driver (driver)
The matchmaking driver. Rooms are cached and queried against a Driver implementation. When scaling your Colyseus servers, you may need to provide a driver option that fits your needs.
See Driver for more details.
Presence (presence)
When scaling Colyseus through multiple processes / machines, you need to provide a presence server. Read more about Scalability, and the Presence API.
import { defineServer, RedisPresence } from "colyseus";
const server = defineServer({
// ...
presence: new RedisPresence()
});Routes (routes)
Type-safe HTTP endpoints for your server, built with createRouter() and createEndpoint().
import { defineServer, createRouter, createEndpoint } from "colyseus";
const server = defineServer({
// ...
routes: createRouter({
hello: createEndpoint("/hello", { method: "GET" }, async (ctx) => {
return { message: "Hello, world!" };
}),
}),
});See HTTP Routes for the full reference, including middleware and CORS.
Express (express)
A callback that receives an Express-compatible app, for binding routes with the classic Express API. With uWebSocketsTransport, the app is provided via the uwebsockets-express compatibility layer.
import { defineServer } from "colyseus";
const server = defineServer({
// ...
express: (app) => {
app.get("/", (req, res) => {
res.send("Hello, world!");
});
},
});Prefer routes for new code: endpoints defined there are type-checked end to end, including on the client SDK.
Before Listen (beforeListen)
An optional callback executed before the server starts listening. Use it to connect to a database or other services first. async is supported: the server waits for it.
import { defineServer } from "colyseus";
const server = defineServer({
// ...
beforeListen: async () => {
await connectToMyDatabase();
},
});Database (database)
Boots a database module (usually @colyseus/database’s db instance) before the matchmaker accepts connections. The database may also contribute default routes, such as the auth endpoints.
import { defineServer } from "colyseus";
import { db } from "./db";
const server = defineServer({
// ...
database: db,
});See Database for the full setup.
Auth (auth)
Controls mounting of the @colyseus/auth routes. Pass an options object to mount them explicitly (useful when database is not in use), or false to disable auto-mounting even when a database would provide defaults.
const server = defineServer({
// ...
auth: {
oauth: true,
prefix: "/auth",
},
});Public Address (publicAddress)
The public address advertised for this process (e.g. "server-1.example.com"). When scaling across multiple machines, each process should advertise its own address. The seat reservation returned to the SDK carries it, so clients connect to the right machine directly.
See Scalability for the multi-process setup.
Logger (logger)
Replace the built-in logger (an alias to console by default) with your own implementation, such as pino or winston.
See Logging for ready-made configurations.
Greeting Banner (greet)
Whether to display the Colyseus greeting banner on server start. Default is true.
Select Process ID to Create Room
The selectProcessIdToCreateRoom is a callback that allows you to customize which process the new rooms should be created at, when your deployment uses multiple Colyseus processes.
By default, the process with the least amount of rooms is selected to create a new room.
import { defineServer, matchMaker } from "colyseus";
const server = defineServer({
selectProcessIdToCreateRoom: async function (roomName: string, clientOptions: any) {
return (await matchMaker.stats.fetchAll())
.sort((p1, p2) => p1.roomCount > p2.roomCount ? 1 : -1)[0]
.processId;
},
});A common alternative is to use the process with least amount of connections:
import { defineServer, matchMaker } from "colyseus";
const server = defineServer({
selectProcessIdToCreateRoom: async function (roomName: string, clientOptions: any) {
return (await matchMaker.stats.fetchAll())
.sort((p1, p2) => p1.ccu > p2.ccu ? 1 : -1)[0]
.processId;
},
});Standalone Matchmaker (isStandaloneMatchMaker)
When set to true, this process will only handle matchmaking and will not spawn rooms locally. Room creation is delegated to other game server processes via IPC.
Default is false.
import { defineServer } from "colyseus";
const server = defineServer({
isStandaloneMatchMaker: true,
});See Standalone Matchmaker for a full setup guide.
Development Mode
When devMode is enabled, the server restores previous rooms and room state after a restart caused by a code change. This option is meant for iterating on room code in a local environment.
Default is false.
import { defineServer } from "colyseus";
const server = defineServer({
devMode: true,
});See Development Mode. If you use Vite, the Vite Plugin provides HMR for both your frontend and server code from a single project.
Graceful Shutdown (gracefullyShutdown)
Whether to register the shutdown routine automatically. Default is true.
If disabled, you should call gracefullyShutdown() method manually in your shutdown process.
import { defineServer } from "colyseus";
const server = defineServer({
gracefullyShutdown: false,
});See Graceful Shutdown.
Methods
Define Room Type
Define room types for the matchmaker using the rooms configuration in defineServer().
- Rooms are not created during configuration
- Rooms are created upon client request (See frontend methods)
Parameters:
room_name- The public name of the room. You’ll use this name when joining the room from the frontendRoomClass- TheRoomclassdefaultOptions- (optional) Default options merged into the client-provided options foronCreate()(room creation only)
const server = defineServer({
rooms: {
// Define "chat" room
chat: defineRoom(ChatRoom),
// Define "battle" room
battle: defineRoom(BattleRoom),
// Define "battle" room with custom options
battle_woods: defineRoom(BattleRoom, { map: "woods" }),
}
})You may define the same room type multiple times with different options. When Room#onCreate() is called, the options will contain the merged values you specified on defineRoom() with the options provided by the client SDK.
Definition Options
The matchmaking-related options (filterBy(), sortBy(), and
enableRealtimeListing()) are documented in
Matchmaking → Matchmaking Options.
Lifecycle Events
You can listen for matchmaking events from outside the room instance scope, such as:
"create"- when a room has been created"dispose"- when a room has been disposed"join"- when a client join a room"leave"- when a client leave a room ((room, client, willDispose))"lock"- when a room has been locked"unlock"- when a room has been unlocked"visibility-change"- when a room’s listing visibility changed ((room, isVisible))"metadata-change"- when a room’s metadata changed
Usage:
const server = defineServer({
rooms: {
chat: defineRoom(ChatRoom)
.on("create", (room) => console.log("room created:", room.roomId))
.on("dispose", (room) => console.log("room disposed:", room.roomId))
.on("join", (room, client) => console.log(client.id, "joined", room.roomId))
.on("leave", (room, client) => console.log(client.id, "left", room.roomId))
}
})Use these events for logging and monitoring purposes only. Do not manipulate a room’s state through them. Use the Room’s Lifecycle Events in your room class instead.
Remove Room Type
Revert a room definition, making a roomName unavailable for matchmaking. This
method is usually not recommended but it may be useful in some scenarios.
server.removeRoomType("battle");Simulate Latency
Colyseus allows you to simulate latency between the server and the client. simulateLatency() is a convenience method for simulating clients with high latency during development.
// Make sure to never call the `simulateLatency()` method in production.
if (process.env.NODE_ENV !== "production") {
// simulate 200ms latency between server and client.
server.simulateLatency(200);
}Make sure to never enable this feature in production environments.
Start Listening
Binds the Transport layer into the specified port.
import { defineServer } from "colyseus";
const server = defineServer({
// ...
});
server.listen(2567);On Before Shutdown
Register a custom callback that is called before the Graceful Shutdown routine starts.
server.onBeforeShutdown(async () => {
// ... custom logic
});See Graceful Shutdown.
On Shutdown
Register a custom callback that is called after the graceful shutdown is fully complete.
server.onShutdown(async () => {
// ... custom logic
});See Graceful Shutdown.
Graceful Shutdown
Triggers the Graceful Shutdown routine.
server.gracefullyShutdown();This method is called automatically when the process receives a SIGINT, SIGTERM, or SIGUSR2 signal, or an uncaughtException.
If gracefullyShutdown: false has been provided on Server constructor, you should call this method manually.
See Graceful Shutdown.
Next Steps
- Room API - Implement rooms and handle client connections
- State Synchronization - Define and sync shared game state
- Netcode - Authoritative input, fixed timestep, and lag compensation
- HTTP Routes - Add custom REST endpoints
- Deployment - Deploy your server to production