Database

Database

The recommended way to persist game data in Colyseus is @colyseus/database, the official persistence layer, built on Drizzle ORM. A single typed connection backs player accounts, cloud saves, leaderboards, live configs, analytics, moderation, and matchmaking.

A single GameDatabase instance exposes:

  • db.auth: user store for @colyseus/auth: bans, session revocation, password management
  • db.saves: versioned cloud saves with optimistic locking
  • db.leaderboards: keep-best scores, seasons, top-N and around-me queries
  • db.configs: typed, hot-reloadable live-ops configuration
  • db.analytics / db.moderation / db.notes: event tracking, roles, and player notes
  • db.segments: declarative player cohorts for targeting
  • DatabaseDriver: a matchmaking driver reusing the same connection

Colyseus itself remains database-agnostic: if your project needs a different stack, bring your own database and query it directly from your rooms.

@colyseus/database was introduced in Colyseus 0.18. Feedback is welcome on the public roadmap.

Installation

npm install --save @colyseus/database

For PostgreSQL, also install the postgres driver:

npm install --save postgres

Quick start

Construct a GameDatabase and pass it to defineServer via the database option. The server boots the database (running migrations) before it starts listening, and automatically mounts the @colyseus/auth routes when that package is installed.

src/app.config.ts
import { defineServer } from "colyseus";
import { GameDatabase } from "@colyseus/database";
 
export const db = new GameDatabase({
    connectionString: process.env.DATABASE_URL,
});
 
export default defineServer({
    database: db,
    // ...rooms, routes, etc.
});

Export the db instance so your rooms can import it. Inside any room lifecycle method, the services are ready to use:

src/rooms/MyRoom.ts
import { Room } from "colyseus";
import { db } from "../app.config";
 
export class MyRoom extends Room {
    async onJoin(client, options) {
        // client.auth was populated by the default static onAuth,
        // which already rejects banned/revoked tokens automatically.
        await db.cloudSaves.load(client.auth.id);
    }
}

Dialects & connection strings

The dialect is auto-detected from the connection string. When omitted, SQLite is used with the default file colyseus.db.

Connection stringDialectNotes
(omitted) or ./game.dbSQLiteFile-based; great for development
:memory:SQLiteEphemeral; useful for tests
postgres://… / postgresql://…PostgreSQLProduction; requires the postgres package
pglite://./data / pglite://:memory:PGliteEmbedded Postgres, no external server
src/app.config.ts
// SQLite (development): defaults to colyseus.db
new GameDatabase();
 
// PostgreSQL (production)
new GameDatabase({ connectionString: process.env.DATABASE_URL });
 
// Embedded PGlite, file-backed
new GameDatabase({ dialect: "pglite", connectionString: "pglite://./data" });

Migrations

The migrations option controls how the schema is applied at boot:

  • "auto" (default): creates missing tables and adds new columns. Idempotent and convenient for development.
  • "skip": does nothing; you manage the schema externally (e.g. a drizzle-kit migrate step in CI before the server starts).
  • { files: "./drizzle" }: runs SQL migration files generated by drizzle-kit. Drizzle tracks applied migrations, so reruns are safe.
src/app.config.ts
new GameDatabase({
    connectionString: process.env.DATABASE_URL,
    migrations: "skip", // schema applied by CI
});

Matchmaking driver

Reuse the same connection as your matchmaking driver (one pool for everything, no separate Redis required):

src/app.config.ts
import { defineServer } from "colyseus";
import { GameDatabase } from "@colyseus/database";
import { DatabaseDriver } from "@colyseus/database/driver";
 
export const db = new GameDatabase({ connectionString: process.env.DATABASE_URL });
 
export default defineServer({
    database: db,
    driver: new DatabaseDriver(), // adopts the GameDatabase connection
});

Next steps

  • Authentication: the built-in @colyseus/auth integration (auto-mounted routes, ban gating, JWT revocation, admin helpers).
  • Services: cloud saves, leaderboards, live configs, analytics, moderation, notes, and the matching room plugins.
  • Customizing built-in table schemas: extend the package’s drizzle tables with your own columns.
  • Bring your own database: ORMs, query builders, Firebase, and the onAuth/onLeave integration patterns.