# Serverpod Migrations

> Serverpod database migrations — when and how to create/apply/repair migrations. Use whenever database schema changes are involved.

- Skill: `serverpod/serverpod-migrations` (Agent Skill)
- Install (CLI): `npx skillmds@latest add serverpod/serverpod-migrations`
- Raw SKILL.md: https://api.skillmd.com/api/skills/serverpod/serverpod-migrations/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: serverpod (https://skillmd.com/u/serverpod)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/serverpod/serverpod-migrations

---


# Serverpod Migrations

Serverpod has a migration system that generates SQL for changes to models with `table` in `.spy.yaml`. The migrations are applied:

- When the `apply_migrations` tool is called via the `serverpod` MCP. Typically during development with a running `serverpod start`.
- When the server is started with `dart run bin/main.dart --apply-migrations` flag. Typically when running the server in production.

## When migrations are needed

- Added, removed, or renamed `table` models or fields in `.spy.yaml`.
- Changed relation fields that alter generated foreign keys.
- Added, removed, or changed indexes.

Migrations are not needed when the project has no database configured (e.g. `config/<runMode>.yaml` with no `database` section).

## Standard flow

The standard flow for creating and applying migrations is simplified when a `serverpod start` is running.

### With a running `serverpod start` and MCP server

When the server is running from `serverpod start` use the `serverpod` MCP to:

1. Create a migration using the `create_migration` tool.
2. Apply the migration using the `apply_migrations` tool.

ALWAYS use the MCP server if it is available.

### ONLY if MCP server fails to connect

When the server is not running from `serverpod start` use the CLI commands to:

1. Ensure the code is generated by running `serverpod generate`.
2. Create a migration using the `serverpod create-migration` command.

## Editing a generated migration

A migration directory holds `migration.sql`, `definition.sql` and the `definition.json`, `definition_project.json` and `migration.json` files.

`migration.sql` MAY be edited by hand after it is created. Two common reasons:

- Adding a data transformation, so existing rows are migrated along with the schema.
- Turning a destructive change into a non-destructive one, by reaching the same end state through intermediate steps — for example add the new column, backfill it from the old one, then drop the old column, instead of dropping and recreating.

Never edit the other files in the directory. `definition.sql` is the full schema, and the `*.json` files are what the next `serverpod create-migration` diffs against, so changing them corrupts every migration created afterwards.

Two rules follow from how migrations are applied:

- A database that has no migrations installed is created from the latest `definition.sql` alone and never runs `migration.sql`. An existing database applies each newer `migration.sql` in order. So the schema an edited `migration.sql` ends up with must stay identical to `definition.sql`, and data transformations in it only affect databases that upgrade through that version.
- Editing a migration that has already been applied does nothing to the databases that ran it. Create a new migration for those.

On the client side (models with `database: client` or `database: all`), the same applies to the migration SQL inside the version's `migration.dart`; its definition SQL and JSON files are equally off limits.

## Repair migrations

If the database is in an inconsistent state, a repair migration brings it back to a consistent state. It is created by reading the live schema and diffing it against a target migration version, so the database must be reachable.

### With a running `serverpod start` and MCP server

1. Create the repair migration using the `create_repair_migration` tool. Optional arguments: `version` (target migration version, defaults to the latest), `tag`, and `force` (required for destructive changes, or when no drift is detected).
2. Apply it using the `apply_migrations` tool, which applies both pending and repair migrations without restarting the server.

ALWAYS use the MCP server if it is available.

### ONLY if MCP server fails to connect

```bash
# Use the `--mode` flag to specify the run mode
# Use the `--version` flag to specify the target version
# Use the `--force` flag to create a migration with destructive changes
# Use the `--tag` flag to name the migration
serverpod create-repair-migration [--mode production] [--version <name>] [--force] [--tag <tag>]
```

Apply the repair migration by restarting the server with `dart run bin/main.dart --apply-repair-migration`. Ask the user to run this command.

