Skip to content
BuildThenTestedSee packages

Migrations that cannot be undone

When the change turns out to be wrong, the old column values and deleted rows are already gone, and the only way back is a full restore from backup, if one exists. Whether stored data stays correct over time. Check it yourself with the steps below; our test adds what a script and a second account can find.

What it looks like

-- 20260315120000_fix_orders.sql
ALTER TABLE orders DROP COLUMN legacy_status;
ALTER TABLE orders ALTER COLUMN total TYPE integer USING total::integer;
DELETE FROM orders WHERE created_at < '2025-01-01';
-- No down migration. No backup step. No copy of the old column.
A migration (a versioned SQL file that changes the database structure) that drops a column, changes a type and deletes rows in one go, with nothing written down about how to get back.

What happens

When the change turns out to be wrong, the old column values and deleted rows are already gone, and the only way back is a full restore from backup, if one exists.

Where it shows up

Descriptive, not a verdict: builders and stacks whose defaults make this reachable, or that a public incident names. Each hub states the tool's own security features.

Check it yourself

Uses your builder's dashboard and your browser. No tools to install.

  1. Open the project's files (in the builder's code view or the synced GitHub repository) and find the supabase/migrations folder.
  2. Open the most recent files and look for statements that begin with DROP, ALTER ... TYPE, DELETE or TRUNCATE.
  3. For each one, look for a way back: a matching down file, a comment naming a backup taken first, or a step that copies the old data before removing it.
  4. Bad result: destructive statements with no reversal path and no backup mentioned anywhere near them.

What we check

We apply each migration to a copy of the schema loaded with sample rows and then try to reverse it. The report lists which changes lose data and which cannot be undone without a restore.

Fix direction

Split destructive changes into two steps: add the new column and copy data first, drop the old one later once the app no longer reads it. Write a reversal for each migration, and take a backup snapshot before running one that drops or retypes anything.

Mechanism documented in: Database Migrations (verified 2026-09-21).

Covered by

Full audit ($1,900, 5 business days)

Both include a re-check after your fixes.

Compare packages

Related patterns

  • No backup that has ever been restoredData integrity

    When data is deleted or corrupted, whether by a bug, an agent or a person, there is either nothing to restore or a backup nobody has proven they can actually bring back.

    High
  • Deletes with no soft delete or audit trailData integrity

    One wrong click, a bug in a filter, or an abused account removes customer data for good, and nobody can say afterwards what was lost or who removed it.

    High
  • Every change goes straight to productionDeploy and config

    A broken build, a bad migration or an agent's misjudged edit reaches real users and real data first, with no place where it could have been caught.

    Medium
  • No automated checks before deployDeploy and config

    Type errors, broken imports and failing behaviour are discovered by users after deploy rather than by a machine before it, and each fix is another untested push.

    Medium

Questions

what is a database migration in supabase

A migration is a SQL file kept under supabase/migrations that records one change to your database structure, such as adding a table or a column. Supabase's CLI creates these files with supabase migration new or by diffing dashboard changes with supabase db diff, and applies them in order. The files are the history of your schema, which is why a change that destroys data should be written with a way back.

can you undo a supabase migration

Not automatically. Supabase's migration docs describe applying migrations forward and resetting a local database to replay them; they do not provide a rollback command for a single migration on a live project. Undoing a change means writing a new migration that reverses it, which only works if the data the first one removed still exists somewhere.

why does my ai generated app drop columns in migrations

When a builder or coding assistant renames or reshapes a field, the shortest SQL that gets there is often a drop and a re-add. The tool has no view of whether the old values matter to you. Check recent migration files for DROP and ALTER ... TYPE statements, and ask for an add-copy-drop sequence instead.

Back to the catalogue, or run the self-check for your stack.