# Migration drift between local and the linked project: stop and diff

`supabase db push` fails or, worse, succeeds against a database whose real schema no longer matches the migration history. The cause is almost always out-of-band changes: someone clicked in the dashboard, ran ad-hoc SQL, or applied a migration locally without committing it.

## Symptom to cause to confirmation to fix

1. Confirm the drift with `supabase db diff` against the linked project. Read the diff carefully: it shows what the migrations would change, which tells you what is out of sync.
2. Decide per change whether the database or the migrations are the source of truth. Dashboard hotfixes belong in a new migration (capture them with `supabase db diff` into a migration file). Local-only experiments that never shipped should be reverted.
3. If the history table is wrong (migrations marked applied that were not, or vice versa), use `supabase migration repair` to fix the history rows. Repair edits history, not schema; run it only after step 2.
4. Re-run `supabase db diff`. Empty diff is the only acceptable state before pushing.
5. Push, then diff again. A clean round trip is the verification.

## Rules that prevent recurrence

Every schema change goes through a migration file, reviewed and committed. The dashboard SQL editor is for reads and emergencies; any emergency write gets a follow-up migration the same day. Agents that "just fix it in the dashboard" are the number one drift source.