> ## Documentation Index
> Fetch the complete documentation index at: https://docs.specific.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Reshape migrations

> Zero-downtime database schema migrations, managed automatically.

Zero-downtime schema migrations using [Reshape](https://github.com/fabianlindfors/reshape), built into Specific.

Reshape uses a 3-phase approach so old and new application code can run against the database at the same time:

1. **Start** - creates the new schema version with views and triggers. Both old and new schemas are available simultaneously.
2. **Rollout** - new application code is deployed and uses the new schema via `search_path`.
3. **Complete** - the old schema and migration artifacts are removed.

## Enabling Reshape

Add a `reshape` block to a postgres definition in `specific.hcl`:

```hcl specific.hcl theme={null}
postgres "main" {
  reshape {
    enabled = true
  }
}
```

With a custom migrations directory (the default is `migrations/`, relative to `specific.hcl`):

```hcl specific.hcl theme={null}
postgres "main" {
  reshape {
    enabled = true
    migrations_dir = "db/migrations"
  }
}
```

## Writing migrations

Migrations are TOML files composed of actions (`create_table`, `add_column`, `alter_column`, `add_index`, `custom`, and more), processed in **lexical order** (`001_first.toml` before `002_second.toml`):

```toml migrations/001_create_users.toml theme={null}
[[actions]]
type = "create_table"
name = "users"
primary_key = ["id"]

  [[actions.columns]]
  name = "id"
  type = "INTEGER"
  generated = "ALWAYS AS IDENTITY"

  [[actions.columns]]
  name = "email"
  type = "TEXT"
  nullable = false
```

<Note>
  Run `specific check` every time you create or edit a migration file. It validates both `specific.hcl` and all migration files, catching errors before they're applied. Without it, invalid migrations silently fail to apply.
</Note>

The full list of actions, with every option and examples, is bundled with the CLI: run `specific docs postgres/reshape/actions`, and `specific docs postgres/reshape/actions/<action>` for a specific one.

## Automatic management in development

When `specific dev` starts with Reshape enabled, migrations are managed for you:

1. **All migrations except the last are completed** - these become permanent schema changes.
2. **The last migration is started but not completed** - so you can iterate on it.
3. **Completed migration files are made read-only** - preventing accidental modification.

While `specific dev` is running:

* **Modifying the last migration file** aborts and restarts that migration. Services keep running - no restart needed, since the schema name doesn't change.
* **Adding a new migration file** completes the previous migration (making it permanent) and starts the new one. Services are restarted to use the new schema.

The development workflow:

1. Write a migration file in the migrations directory.
2. Run `specific check` to validate.
3. `specific dev` applies it automatically.
4. Iterate on the migration - run `specific check` after **every** change.
5. When ready, add a new migration file to lock in the previous one.

If you need to modify a completed migration, change its file permissions first; completed files are read-only on purpose.

## Connection strings

When Reshape is enabled, `postgres.<name>.url` automatically includes the correct `search_path`. No service configuration changes needed:

```hcl specific.hcl theme={null}
service "api" {
  build = build.api
  command = "node server.js"

  env = {
    DATABASE_URL = postgres.main.url  # Automatically includes search_path
  }
}
```

## Manual migration commands

You can also control migrations directly:

```bash theme={null}
# Validate migration files (works without specific dev running)
specific reshape check

# Start a migration (applies new schema while keeping the old one available)
specific reshape start

# Check migration status on a specific database
specific reshape status main

# Complete a migration (removes old schema)
specific reshape complete main

# Abort a migration (rolls back to old schema)
specific reshape abort main
```

Most actions need database access; if `specific dev` isn't running, the database is started temporarily. `check` only validates file syntax and runs anytime.

## Production

During `specific deploy`, migrations follow the same 3-phase flow, coordinated with the service rollout: pending migrations are started before the new code rolls out, and completed once the rollout succeeds. If the rollout fails, the migrations are aborted automatically and the database rolls back to the old schema.
