DatabaseCustomizing schemas

Customizing built-in table schemas

Every service in @colyseus/database is backed by a Drizzle table you can extend with your own columns. Use the per-dialect tables factory to spread the built-in columns into a custom table, then pass it via the schemas option. Services keep working and return your custom columns with full type inference.

Built-in tables

KeyPhysical tableUsed byPurpose
userscolyseus_usersdb.auth + @colyseus/authPlayer accounts (email, password hash, anonymous flag, ban fields, token version)
configscolyseus_configsdb.configsLive-ops config key/value store
cloudSavescolyseus_cloud_savesdb.savesPer-user, per-slot save data with version
leaderboardscolyseus_leaderboardsdb.leaderboardsLeaderboard definitions
leaderboardEntriescolyseus_leaderboard_entriesdb.leaderboardsScore rows per (board, user, season)
analyticsEventscolyseus_analytics_eventsdb.analyticsEvent log written by track()
rolescolyseus_rolesdb.moderationModeration roles + scoped collection permissions
userNotescolyseus_user_notesdb.notesAdmin notes attached to users
adminAuditcolyseus_admin_auditdb.auditAdmin action audit log
roomCachescolyseus_room_cachesDatabaseDriverMatchmaker room cache (driver-owned; customize via the driver’s schema option, not schemas)

Example: extending users

src/app.config.ts
import { GameDatabase, tables } from "@colyseus/database";
import { text, integer } from "drizzle-orm/sqlite-core";
 
const users = tables.sqlite.users("users", {
    displayName: text("display_name"),
    level: integer("level").notNull().default(1),
});
 
export const db = new GameDatabase({
    connectionString: "./game.db",
    schemas: { users },
});

The factory is available on both dialects: tables.sqlite.<name> and tables.pg.<name>. For finer control, you can also spread the column maps directly (columns.sqlite.<name> / columns.pg.<name>) into a hand-rolled sqliteTable(...) / pgTable(...).

The raw Drizzle instance is available as db.drizzle (typed against your resolved schema) for any query the services don’t cover.