This document describes the naming conventions for Prisma migration files, the rollback process for development and production environments, and guidance on irreversible migrations.
All database migrations are managed via Prisma Migrate. Migration files are generated using the prisma migrate CLI and follow a strict naming convention.
<timestamp>_<description>
| Component | Format | Example |
|---|---|---|
timestamp |
UTC timestamp in YYYYMMDDHHMMSS |
20260624120000 |
separator |
Underscore (_) |
_ |
description |
Lowercase, hyphen-delimited words describing the change | add_creator_wallet_index |
Full example:
20260624120000_add_creator_wallet_index
This produces a directory structure under prisma/schema/migrations/:
prisma/schema/migrations/
└── 20260624120000_add_creator_wallet_index/
├── migration.sql
└── migration_lock.toml
- Timestamps must be strictly increasing. Never create a migration with a timestamp older than the latest existing migration.
- Descriptions use snake_case (underscore-delimited) to keep file paths readable.
- Descriptions should be brief but descriptive — enough to identify the purpose at a glance (e.g.,
add_creator_wallet_index,remove_deprecated_balance_column). - Do not rename migration directories after creation. Prisma tracks applied migrations in the
_prisma_migrationstable by directory name; renaming breaks the link.
# After editing a .prisma schema file, run:
pnpm exec prisma migrate dev --name add_creator_wallet_indexPrisma automatically prepends the UTC timestamp. The resulting directory will be:
prisma/schema/migrations/20260624120000_add_creator_wallet_index/migration.sql
pnpm exec prisma migrate statusThis shows which migrations have been applied, which are pending, and whether the database schema matches the expected state from the Prisma schema files.
In development, you can roll back migrations interactively using Prisma's built-in reset or by applying a down migration manually.
This drops all data and re-applies all migrations from scratch. Use this when schema drift is severe or when you do not need to preserve development data.
pnpm exec prisma migrate reset- Drops the database and recreates it.
- Re-applies all migrations.
- Optionally runs the seed script.
- All data in the development database is lost.
To roll back the most recent migration while keeping data:
-
Identify the migration to roll back:
pnpm exec prisma migrate status -
Edit the generated
migration.sqlto create a down migration script that reverses the SQL (see Section 3 for guidance on writing reversible migrations). -
Apply the rollback manually via
psql:psql "$DATABASE_URL" < path/to/down-migration.sql
-
Remove the migration record from
_prisma_migrationsso Prisma knows it is no longer applied:DELETE FROM _prisma_migrations WHERE migration_name = '20260624120000_add_creator_wallet_index';
-
Delete the migration directory:
rm -rf prisma/schema/migrations/20260624120000_add_creator_wallet_index
-
Verify the state:
pnpm exec prisma migrate status # Should show no pending migrations and the rolled-back schema as current.
Prisma does not natively support "rolling back to version N." Instead, reset and re-apply up to a target migration:
# 1. Reset the database
pnpm exec prisma migrate reset
# 2. Apply migrations up to (and including) a specific one
pnpm exec prisma migrate resolve --applied "20260623100000_previous_migration_name"Warning
This approach recreates the database from scratch. Do not use this on a database with production data.
Rolling back a migration in production carries inherent risk. Follow the forward-only principle: prefer deploying a new migration that undoes the change rather than reverting an already-applied migration.
-
Create a new migration that reverses the schema change:
-- Example: undo "DROP COLUMN IF EXISTS balance" ALTER TABLE creator ADD COLUMN IF NOT EXISTS balance DECIMAL(20, 7) NOT NULL DEFAULT 0;
-
Generate the migration:
pnpm exec prisma migrate dev --name revert_add_creator_wallet_index -
Deploy the rollback migration as part of a standard release.
-
Verify the schema is restored:
pnpm exec prisma migrate status
If you need to roll back the application code immediately and the migration cannot be reversed with a follow-up migration (e.g., a forward-only migration has already run):
- Redeploy the previous app version from the last green release tag.
- Disable the affected code path with a feature flag if the new schema cannot be read by the old code.
- Do not revert migrations against production data unless you have verified that no writes have occurred against the new columns/tables.
- Open a hotfix issue to adapt the code to the current schema.
Important
Never run prisma migrate reset or prisma migrate dev against a production database. These commands are designed for local development only.
Some schema changes cannot be cleanly reversed without data loss. These are called forward-only or irreversible migrations.
| Operation | Why It Is Irreversible |
|---|---|
DROP COLUMN |
The column and its data are permanently removed (unless backed up beforehand). |
DROP TABLE |
The entire table and all its data are removed. |
ALTER COLUMN ... TYPE (narrowing) |
Changing TEXT to VARCHAR(100) truncates data; the original longer values are lost. |
ALTER COLUMN ... SET NOT NULL |
If rows with NULL exist and are deleted during migration, that data is unrecoverable. |
RENAME COLUMN / RENAME TABLE |
Old references in code or other migrations may break silently. |
Adding a UNIQUE constraint |
If duplicate values exist, the migration fails. Rolling back does not restore them. |
-
Write a backup script first:
pg_dump "$DATABASE_URL" \ -t target_table \ --column-inserts \ --data-only \ > backup_target_table_$(date +%Y%m%d).sql
-
Make the migration reversible in two phases where possible:
- Phase 1 (additive): Add the new column/table as nullable. Deploy and let the application write to both old and new locations.
- Phase 2 (destructive): After confirming no code reads the old structure, drop it in a follow-up release.
-
Document the irreversible migration in the migration SQL file as a SQL comment:
-- IRREVERSIBLE: Drops the legacy `balance` column. -- Data in this column will be permanently lost. -- Backup: see operations runbook at docs/ops/backup-balance-column.md ALTER TABLE creator DROP COLUMN IF EXISTS balance;
-
Flag it in the release notes so operators are aware before deploying.
- Production data backed up (table-level dump).
- Irreversible operation documented in the migration SQL file.
- Release notes call out the irreversible change.
- Rollback plan documented in the release PR.
- Feature flag exists to disable the code path depending on the new schema (if applicable).
# 1. Edit the Prisma schema files in prisma/schema/
# 2. Generate the migration
pnpm exec prisma migrate dev --name short_description_of_change
# 3. Review the generated SQL in prisma/schema/migrations/<timestamp>_<name>/migration.sql
# 4. Run tests
pnpm testpnpm exec prisma migrate deploypnpm exec prisma migrate statuspnpm exec prisma migrate diff \
--from-migrations prisma/schema/migrations \
--to-schema-datamodel prisma/schema \
--script- One conceptual change per migration. Avoid bundling unrelated schema changes in a single migration file. This makes rollbacks and code reviews easier.
- Review the generated SQL before applying it. Prisma generates correct SQL in most cases, but always verify that the
migration.sqlfile matches your intent. - Test migrations against a staging database before deploying to production.
- Keep migrations under version control. All migration directories inside
prisma/schema/migrations/should be committed to Git. Never delete committed migration directories. - Ensure forward compatibility. New columns should be nullable or have a safe default so a partial rollout does not break older application replicas.
- Use migration checksums. Prisma tracks a SHA-256 checksum for each migration. If the migration SQL file is modified after being applied, Prisma will detect the checksum mismatch and refuse to proceed. If you must modify an already-applied migration, use
prisma migrate resolveto reconcile the checksum.
- Release Checklist — Pre-deploy checks for migrations.
- Configuration Guide — Database connection configuration.
- Read-Model Rebuild — Rebuilding derived read models after schema changes.