Change the database schema
Add or change a table and ship the migration that goes with it. packages/db/prisma/schema.prisma is generated; never edit it.
Before you add a table, check whether per-user or per-organization values without filtering, sorting or foreign keys fit the metadata sidecar instead (setUserMetadataValue / setOrganizationMetadataValue); it needs no migration.
- Edit the model where it lives:
- a core module:
packages/db/prisma/base.prisma, under the module's// ── MODULE: <name> ──banner; - an extended module: its own
packages/<name>/prisma/<name>.prismafragment, under the same banner. Extended modules never touchbase.prisma.
- a core module:
- Reassemble the schema:
pnpm gen - Write the migration without applying it:
It appears inpnpm --filter @monark/db exec prisma migrate dev --create-only --name <what-changed>packages/db/prisma/migrations/<timestamp>_<what-changed>/migration.sql. - Open
migration.sqland delete the lineDROP INDEX "DataRecord_data_gin";if it's there. Prisma can't see that hand-written index and tries to drop it in every migration. - Apply the migration to your local database:
pnpm db:migrate - Check the migrations reproduce the schema, using a throwaway Postgres:
docker run --rm -d -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=shadow -p 5433:5432 postgres:16-alpine SHADOW_DATABASE_URL=postgresql://postgres:postgres@localhost:5433/shadow pnpm check:migrations - Commit the base or fragment change, the regenerated
schema.prismaand the migration together.
Good to know:
- The database scripts read
packages/db/.env, soDATABASE_URLandDIRECT_URLmust be set there as well as inservices/api/.env. Bootstrap does this. - Never edit a migration that has been applied anywhere else. Add a new one.
- Plain
migrate devwithout--create-onlywaits for keyboard input and hangs in scripts and agent sessions.
Next: Write tests