Colyseus 0.17 is here!
Automatic reconnection, full-stack TypeScript safety, new defineServer() API, and more!
Iβm thrilled to share version 0.17 of Colyseus is here! π
This version brings automatic reconnection, full-stack TypeScript safety, a unified defineServer() API, and many quality of life improvements to the framework.
Automatic Reconnection β¨
Handling disconnections gracefully has always been a challenge in real-time multiplayer games. With 0.17, the client SDK now supports automatic reconnection β preserving your callbacks and state listeners during abnormal closures, so players can seamlessly return to their session.
On the server side, two new lifecycle methods make reconnection handling straightforward:
class MyRoom extends Room { async onDrop(client: Client, code: number) { // flag as disconnected (player may return!) this.state.players.get(client.sessionId).disconnected = true; // allow reconnection for 10 seconds await this.allowReconnection(client, 10); }
async onReconnect(client: Client) { // flag as connected (player is back!) this.state.players.get(client.sessionId).disconnected = false; }
async onLeave(client: Client, code: number) { // delete from state (player not coming back) this.state.players.delete(client.sessionId); }}onDrop() is triggered when a client disconnects abnormally, giving you the chance to hold their spot. If they reconnect in time, onReconnect() fires. If they donβt, onLeave() takes over as usual. The client SDK also provides matching onDrop() and onReconnect() callbacks, and can skip the handshake when local state is available β making reconnection nearly instant.
See Reconnection π for more.
Unified defineServer() with Full-stack Type Safety π
The new Server() constructor and @colyseus/tools have been consolidated into a single, clean entry point β defineServer():
export const server = defineServer({ rooms: { my_room: defineRoom(MyRoom), },});Because the server definition is now a typed export, your client can import the server type directly for end-to-end type safety across room state, messages, and HTTP routes:
import type { server } from "../backend/src/app.config.ts";const client = new Client<typeof server>("http://localhost:2567");This means autocompletion and type checking for room names, state structures, message types, and more β all inferred from your server definition. No more stringly-typed room joins or manual type wrangling.
New HTTP Routes & Playground π€οΈ
Colyseus 0.17 introduces a new API for declaring typed HTTP routes on the server side, powered by Zod for schema validation:
import { createEndpoint, createRouter } from "colyseus";import { z } from "zod";
const itemEndpoint = createEndpoint("/item/:id", { method: "POST", query: z.object({ include: z.string().optional() }), body: z.object({ name: z.string() }).optional(),}, async (ctx) => { // (...) process the request return ctx.json({/* (...) response */})});
export const server = defineServer({ routes: createRouter({ itemEndpoint, }),});As a bonus, your routes automatically get a Playground β a Postman-like UI thatβs auto-generated from your route definitions, making it easy to test and explore your API during development.

New Callbacks API for TypeScript π
A new Callbacks API brings Unity-like schema callbacks to TypeScript, offering a familiar pattern for listening to state changes:
import { Callbacks } from "@colyseus/sdk";
var callbacks = Callbacks.get(room);
callbacks.onAdd("players", (player, sessionId) => { // player added! // (...)
callbacks.onChange(player, () => { // player changed // (...) });});
callbacks.onRemove("players", (player, sessionId) => { // player removed // (...)});More new features & improvements π
QueueRoomβ A new built-in room type for queue-based matchmaking.- Rate limiting β New
maxMessagesPerSecondoption to rate-limit room messages, forcibly closing connections that exceed the threshold. room.ping(callback)β New method for measuring round-trip latency from the client.- Latency-based server selection β New
ColyseusSDK.selectByLatency(endpoints)andsdk.getLatency()for picking the closest server. - Schema
$refIdaccess β Now accessible on both client-side and server-side viainstance[$refId]. - Embedded debug inspector β New
@colyseus/sdk/debugmodule provides a realtime debug/inspector for rooms. On Unity: Window β Colyseus β Room Inspector. LobbyRoomimprovements β Fixed ghost rooms in lobby on room dispose;.setMetadata()now automatically callsupdateLobby()..setMatchmaking()β Batch modify a roomβs matchmaking entry (metadata,locked,maxClients, etc.) in a single operation.- Express v5 support β Added compatibility with Express v5.
patchRate=0fix β SettingpatchRate=0no longer stopsclockintervals and timeouts from working.- Experimental β New PostgreSQL matchmaking driver and Traefik module.
Breaking changes π¨
Migrating from version 0.16 to 0.17 shouldnβt take long. Hereβs an overview of the breaking changes:
- Room generic type changed from
Room<State, Metadata>toRoom<{ state?, metadata?, client? }>. onLeave(client, code)now receives a closecodenumber instead of aconsentedboolean flag..setSeatReservationTime()moved to a.seatReservationTimeoutproperty.Protocol.WS_*close codes moved toCloseCode.*(newCloseCode.SERVER_SHUTDOWN).- Roomβs presence pub/sub now unsubscribes automatically during
onDispose()β no need to manually unsubscribe.
See Migrating to 0.17 π for more details.
The Future: Version 1.0 and Beyond π
Colyseus is independent and open-source β developed and maintained by a solo indie developer, driven by the feedback, bug reports, and contributions from a passionate community. Thereβs no venture capital or corporate backing behind this project β just a shared commitment to building the best multiplayer framework together. Your sponsorship directly funds the development of new features, bug fixes, and the path to version 1.0.
If Colyseus powers your game or project, consider becoming a sponsor to help keep the framework thriving. Every contribution β big or small β makes a real difference and ensures Colyseus stays free, independent, and actively maintained for everyone.
π Special shoutout to Scorewarrior, Pixels.xyz, Petr Kharitonov, Bloxd, Poki, 0x&, and all our supporters π