Guides

How to review database migrations before they merge

Put a specialist reviewer on the pull requests that touch migrations, checking locking, backfills, and rollout order.

A migration is the change most likely to take production down and the least likely to get a careful review. The diff is short, it looks mechanical, and the failure mode (a lock held on a 50M-row table during deploy) is invisible in the code. General review skims it.

A paths filter puts a specialist on exactly those pull requests, with a prompt about migration safety instead of code style.

ellipsis:
  version: v1
  name: Schema migration reviewer
  description: Reviews database migrations before they merge

claude:
  model: claude-opus-4-8
  system: |
    You review database migrations for production safety.

    Inspect the new migrations, the model changes, and any deployment
    code in the diff. Check for locking behavior that blocks writes on
    a large table, missing backfills for new non-null columns, missing
    indexes on new foreign keys, and rollout ordering that breaks if
    the migration and the code deploy in the wrong order.

    Comment on the specific line with the specific change you want.
    A migration that is safe as written gets a one-line confirmation,
    not invented concerns.

trigger:
  type: react
  pull_request:
    on: [opened]
    repositories: [splitshift-api]
    paths: ["**/migrations/**"]

sandbox:
  repositories:
    - name: splitshift-api
    - name: splitshift-infra

budget:
  session: 0.80
  day: 4.00

paths matches against the full changed-file set of the pull request, so the agent runs only when a migration is actually in the diff. dani-okoro adds a non-null expired_at column and the review lands before anyone else looks:

migrations/0042_expired_at.py:14 — adding a NOT NULL column with a
default rewrites the whole table under an ACCESS EXCLUSIVE lock.
On trade_requests (~50M rows) that blocks writes for minutes.

Split it: add the column nullable, backfill in batches, then set
NOT NULL in a follow-up migration once the backfill completes.

Also: trades/models.py:88 starts reading expired_at in the same
pull request. If the code deploys before the migration, every
read raises. Gate the read behind a check or land the migration
first.

Why opened and not pushed

A migration reviewer wants to look once, at the whole change, and say something substantial. opened fires on open, reopen, and ready-for-review. Compare How to review every pull request as commits land, where code_review follows each push because the job is incremental.

Both reviewers on one pull request

React fires every matching config independently. A pull request that touches a migration gets the general reviewer and this one, which is the intent: one reads the code, one reads the migration. They do not need to know about each other.

The sandbox includes splitshift-infra even though the trigger only watches splitshift-api. The deploy code lives there, and rollout ordering cannot be judged without it. sandbox.repositories is independent of the watch set; the triggering repository is always cloned regardless.

Next

Scope a reviewer by author or branch instead of path with the filters in the agent config reference, or see Budgets for what a per-session cap does when it is reached.