Skip to content

ADR-0006 — Prisma schema split across 3 files

Status: Accepted Date: 2026-04-16 Author(s): Platform engineering

Context

The ebit-api data model contains 81 models, views, and enums across three PostgreSQL schemas (public, blackjack, speed_roulette). A single schema.prisma file would exceed 2,200 lines, mixing unrelated domains — user accounts and betting alongside blackjack table state alongside speed-roulette game rounds. Prisma 5.15+ supports the prismaSchemaFolder preview feature, which allows a directory of .prisma files to be treated as a single logical schema.

Decision

Split the schema into three files under libs/_prisma/src/schema/:

File Lines Models/views PostgreSQL schema
api.prisma ~1,976 70 public
blackjack.prisma ~157 8 blackjack
speed_roulette.prisma ~74 3 speed_roulette

The generator and datasource blocks live in api.prisma:1-14 with four preview features enabled:

generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["prismaSchemaFolder", "multiSchema", "views", "tracing"]
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
  schemas  = ["public", "blackjack", "speed_roulette"]
}

package.json:210-213 points Prisma at the directory (not a file):

"prisma": {
  "schema": "libs/_prisma/src/schema"
}

Each model uses @@schema("blackjack") or @@schema("speed_roulette") to declare its PostgreSQL schema. Models in api.prisma default to public.

Alternatives considered

  1. Single monolithic schema.prisma. Rejected: 2,200+ lines with three unrelated domains interleaved. Merge conflicts are frequent when backend and game teams edit the same file. The file becomes unnavigable without IDE search.

  2. Separate Prisma clients per schema (3 generators, 3 clients). Rejected: cross-schema relations (e.g., SpeedRouletteBet references User in public) would require manual joins instead of Prisma's relation API. Three PrismaClient instances triple connection pool overhead and complicate transaction boundaries.

  3. One file per model (80+ files). Rejected: Prisma's prismaSchemaFolder supports it, but 80 files creates excessive filesystem noise. The natural split is by PostgreSQL schema — each file maps to one @@schema, which matches the database boundary and the team ownership boundary.

Consequences

  • All prisma CLI commands (generate, migrate, db push) must use --schema=libs/_prisma/src/schema or rely on the package.json prisma.schema directive. The npm scripts (db:migrate:dev, prisma:generate) already handle this — never call npx prisma directly.
  • Adding a model to the blackjack or speed-roulette domain means editing the domain-specific file, not api.prisma. The @@schema() directive must match the file's domain.
  • The prismaSchemaFolder preview feature must remain enabled. Removing it reverts Prisma to expecting a single file, breaking the build.
  • Cross-schema Prisma relations work transparently at the query level but require PostgreSQL's cross-schema foreign key support — all three schemas live in the same database.

References

  • libs/_prisma/src/schema/api.prisma:1-14 — generator + datasource with preview features
  • libs/_prisma/src/schema/blackjack.prisma — 8 blackjack models
  • libs/_prisma/src/schema/speed_roulette.prisma — 3 speed-roulette models
  • ebit-api/package.json:210-213prisma.schema directory pointer