# migration plan (/docs/cli/migration-plan) > For the complete Prisma documentation index, see [llms.txt](https://www.prisma.io/docs/llms.txt). A markdown version of any docs page is available by appending `.md` to its URL. Plan an on-disk migration from Prisma ORM contract changes. Location: CLI > migration plan `migration plan` compares the emitted contract against a starting contract and produces a new migration package with the required operations. The starting contract is whatever `--from` names, or the [ref](https://www.prisma.io/docs/cli/migration-ref) named `db` when `--from` is absent. With neither, what happens depends on the migrations already on disk: * **`migrations/app/` is empty.** The plan starts from an empty database and contains the full `CREATE` operations for the whole contract. This is the first migration in a new project. The command says so under its summary (`No db ref set — planning from an empty database`), and `--json` output carries `fromDefaulted: true`, so a plan that recreates a database you already have is easy to spot. If a database already exists, run `db init`, `db update`, or `db sign` first. * **Migrations already exist.** The command refuses with `MIGRATION.PLAN_ORIGIN_UNKNOWN` rather than write a full-create package that no real database could apply. The error names the three exits: `migration ref set db ` to point the ref at the state your database is on, `--from ` to name the origin for this one plan, or `--from @empty` to plan from an empty database deliberately. Keep the `db` ref current and you never see the refusal. [`db init`](https://www.prisma.io/docs/cli/db-init) and [`db update`](https://www.prisma.io/docs/cli/db-update) advance it for you when you run them without `--db`; with `--db` you have to add `--advance-ref db`. [`db sign`](https://www.prisma.io/docs/cli/db-sign) advances it whenever it signs, `--db` or not. [`db migrate`](https://www.prisma.io/docs/cli/db-migrate) advances nothing unless you pass `--advance-ref db`. ### The automatic baseline [#the-automatic-baseline] Say `migrations/app/` has no migrations yet, the `db` ref is set, and `migrations/snapshots/` holds a copy of the contract the ref points at. Then `migration plan` writes a baseline: a migration from an empty database to the ref's contract. If your emitted contract has changed since then, the same run also writes a second migration with those changes. Expect one or two new directories in `git status`. `db migrate` never applies the baseline to a database that already records which contract it matches, such as one you ran `db sign` on. It applies only the migrations after the contract that database records. The baseline only creates things, because it is planned from an empty database, so it never removes data. The second migration can remove data, and `migration plan` asks about it before it writes either one, as [Renames and data loss](#renames-and-data-loss) describes. If a migration already starts from the contract the `db` ref points at, `migration plan` writes a second migration that starts from the same contract, so the [migration history](https://www.prisma.io/docs/orm/migrations/the-migration-graph) splits into two branches. This happens, for example, after `db migrate` without `--advance-ref db`, which applies migrations but leaves the `db` ref where it was. `migration plan` still writes the migration and prints a warning. A database that has already run the existing migration then has no migration leading to your new contract, so `db migrate` on that database fails with `MIGRATION.PATH_UNREACHABLE`. To build on the newest migration instead, delete the directory this run wrote and plan again with `--from` set to the newest migration's directory name. The command is offline, so it does not need a database connection. ## Usage [#usage] #### bun ```bash bunx prisma migration plan --name add_users_table ``` #### pnpm ```bash pnpm prisma migration plan --name add_users_table ``` #### yarn ```bash yarn prisma migration plan --name add_users_table ``` #### npm ```bash npx prisma migration plan --name add_users_table ``` ## Options [#options] | Option | What it does | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `--name ` | Sets the migration directory name suffix. | | `--from ` | Uses a specific starting contract state instead of the `db` ref. Accepts a [contract reference](https://www.prisma.io/docs/orm/migrations/the-migration-graph#contract-reference-forms): a hash, a hash prefix, a [ref name](#contract-references), a migration directory name, [`^`](#contract-references), or [`@empty`](#contract-references). `@db` is not accepted here, because `migration plan` is offline and cannot read a database. `@contract` is not accepted either. | | `--to ` | Sets the destination contract state. Defaults to the emitted contract. Accepts the same forms as `--from`, except `@empty`, which is refused as a destination. | | `--rename :` | Renames a model or a field and keeps its rows, instead of dropping and creating its table or column. Repeatable. See [Renames and data loss](#renames-and-data-loss). | | `--delete ` | Lets the migration lose the data of a model, a field, or a table no model stores. For a type change, accepts the database's own cast. Repeatable. | | `--convert ` | For a type change that can lose values, writes an `alterColumnType` whose conversion you fill in. Repeatable. See [Type changes and required fields](#type-changes-and-required-fields). | | `--backfill ` | For a new required field or a field made required, writes a backfill step you fill in, instead of a temporary value. Repeatable. See [Type changes and required fields](#type-changes-and-required-fields). | | `--config ` | Read this config file instead of `./prisma.config.ts`. | | `--json` | Prints a machine-readable result. | ### Contract references [#contract-references] A ref name is a name you gave a contract state with [`migration ref set`](https://www.prisma.io/docs/cli/migration-ref), such as `prod`. `^` is a migration directory name followed by `^`, and it names the contract state before that migration, while the directory name alone names the state after it. `@empty` names the empty database, before any migration. [Contract references each command accepts](https://www.prisma.io/docs/orm/migrations/the-migration-graph#contract-reference-forms) lists the forms for every command. ## Renames and data loss [#renames-and-data-loss] When the migration would lose data, because it drops a model, a field, a table or a collection, or changes a field's type in a way that can change values, `migration plan` asks you what to do before it writes anything. Answer each question on the command line: * `--delete ` lets the data go. A subject is `Model`, `Model.field`, or, for data no model stores, its storage name. * `--rename :` keeps the data. The migration renames the table or column, and the constraints and indexes named after it, instead of dropping and creating it. Each side is `Model`, `namespace.Model`, `Model.field` or `namespace.Model.field`, and a field's model is named as the new contract names it: `--rename Profile:User --rename User.name:User.fullName`. A rename on the command line is planned from the start, so the drop it replaces is never asked about. * `--convert ` answers a type change that can lose values: the migration gets a `placeholder(...)` call that you replace with your own conversion code. #### bun ```bash bunx prisma migration plan --name rename_full_name --rename User.name:User.fullName ``` #### pnpm ```bash pnpm prisma migration plan --name rename_full_name --rename User.name:User.fullName ``` #### yarn ```bash yarn prisma migration plan --name rename_full_name --rename User.name:User.fullName ``` #### npm ```bash npx prisma migration plan --name rename_full_name --rename User.name:User.fullName ``` In a terminal, the command asks the questions you did not answer with a flag. With `--yes`, in a CI job, or with `--no-interactive`, where it cannot ask, it fails with `CLI.CONSENT_REQUIRED` instead. The error lists each question, and its next actions give the flags to add. `--rename` is offered only for a model or field the new contract no longer has, so a field whose type changes is answered with `--convert` or `--delete`. `--confirm` answers none of these questions. Dropping an index, a unique or foreign-key constraint, a check, a default or a native enum type, and setting `NOT NULL`, lose no data, so the command asks nothing about them. On MongoDB, a model rename renames its collection and keeps its documents, indexes and validator, and a field rename renames the field in every document that holds it. Removing a field from a model removes it from every document that holds it, so the command asks about it as it asks about a dropped collection: answer with `--delete User.nickname` or `--rename User.nickname:User.`. The planner refuses a rename of the field stored as `_id`, of a field whose stored name contains `.` or starts with `$`, of a time-series collection, and of a variant whose discriminator value changes, and says what to do instead. On MongoDB, `--rename` and `--delete` name fields by their names in the schema, not by the names they are stored under. For a field `id ObjectId @id @map("_id")`, write `--rename User.id:User.userId`, not `User._id`. The first MongoDB migration you plan after upgrading from a release before `8.0.0-rc.19` is the exception. The [upgrade instructions](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/) include a script that rewrites the copies of your old contract under `migrations/`, and those copies name each field by its stored name. That first migration starts from such a copy, so in it you name the old field by its stored name and the new field by its schema name. For a field that was `name String @map("display_name")` and is now `title String`, write `--rename User.display_name:User.title`. From the next migration on, use schema names only. ## Type changes and required fields [#type-changes-and-required-fields] On PostgreSQL and SQLite, a type change that can lose values, such as `String` to `Int` or a longer `VarChar` to a shorter one, is a question like a drop. Answer it in one of two ways: * `--convert ` writes an `alterColumnType` with `using: placeholder(':convert')`. Replace the placeholder with the conversion as SQL over the column, such as `using: '"age"::integer'`, then run `node migration.ts`. On SQLite the slot is the column's copy expression in `recreateTable`, such as `copyExpressions: { age: 'CAST("age" AS INTEGER)' }`. * `--delete ` lets the database's own cast run. It may cut or round values, and a value it cannot cast fails the apply. A new required field on a table with rows gets a temporary value in the existing rows, such as `''` for text or `0` for a number, and the command's output names it. An optional field made required is tightened directly, so the apply fails while any row holds `NULL`, with a message that counts those rows. To fill the rows yourself, pass `--backfill `: the migration gets a `dataTransform` step with `check` and `run` placeholders to fill in, as [Editing a migration](https://www.prisma.io/docs/orm/migrations/editing-a-migration) shows. A new unique, primary-key or foreign-key field has no temporary value, so use `--backfill` when the table has rows. #### bun ```bash bunx prisma migration plan --name age_to_int --convert User.age --backfill User.displayName ``` #### pnpm ```bash pnpm prisma migration plan --name age_to_int --convert User.age --backfill User.displayName ``` #### yarn ```bash yarn prisma migration plan --name age_to_int --convert User.age --backfill User.displayName ``` #### npm ```bash npx prisma migration plan --name age_to_int --convert User.age --backfill User.displayName ``` ## When nothing in the database changes [#no-database-change] If the storage part of the contract did not change, `migration plan` writes nothing and reports `No changes detected between contracts`. That is not an error, and there is nothing to do. If the storage part changed but the database needs no change, `migration plan` writes nothing and fails with `MIGRATION.PLANNING_FAILED`. This happens after a Prisma upgrade that changes how `contract.json` records values, after you change how a field's values are written in `contract.json` while its database type stays the same, or after you change a control policy. In that case the message gives the next step: * If you deploy with migrations, run `prisma migration new --from `, with the hash from the message, to write a migration with no operations, then `prisma db migrate`. * If you manage the database with `db init` or `db update`, run [`prisma db sign`](https://www.prisma.io/docs/cli/db-sign) on each database instead. If you expected the database to change, report it with the output of `prisma migration plan --json`. ## Recommended flow [#recommended-flow] #### bun ```bash bunx prisma contract emit bunx prisma migration plan --name add_users_table bunx prisma migration show ``` #### pnpm ```bash pnpm prisma contract emit pnpm prisma migration plan --name add_users_table pnpm prisma migration show ``` #### yarn ```bash yarn prisma contract emit yarn prisma migration plan --name add_users_table yarn prisma migration show ``` #### npm ```bash npx prisma contract emit npx prisma migration plan --name add_users_table npx prisma migration show ``` Review the generated migration package before applying it with [`db migrate`](https://www.prisma.io/docs/cli/db-migrate). ## Planning a rollback [#planning-a-rollback] Because `--to` accepts `^` (the source contract of a migration), you can plan a migration that walks back a change: #### bun ```bash bunx prisma migration plan --to ^ --name rollback ``` #### pnpm ```bash pnpm prisma migration plan --to ^ --name rollback ``` #### yarn ```bash yarn prisma migration plan --to ^ --name rollback ``` #### npm ```bash npx prisma migration plan --to ^ --name rollback ``` ## When to use migration plan [#when-to-use-migration-plan] Use `migration plan` when your team wants database changes reviewed in version control. For local prototypes where review is not needed, [`db update`](https://www.prisma.io/docs/cli/db-update) is usually faster. If the generated migration is not the migration you want, use [`migration new`](https://www.prisma.io/docs/cli/migration-new) and author the migration manually. ## Related pages - [`auth`](https://www.prisma.io/docs/cli/auth): Sign in to your Prisma account from the CLI, sign out, and manage workspace sessions. - [`branch`](https://www.prisma.io/docs/cli/branch): List platform branches for a project. - [`bucket`](https://www.prisma.io/docs/cli/bucket): Create and manage object-store buckets. - [`Configuration`](https://www.prisma.io/docs/cli/configuration): Configure Prisma ORM CLI commands with prisma.config.ts and global flags. - [`contract emit`](https://www.prisma.io/docs/cli/contract-emit): Emit Prisma ORM contract artifacts.