Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Existing Database

If you have an existing database — whether managed by another migration tool or maintained manually — pgmagmig can capture its current schema and take over migration management from there.

1. Bootstrap with your existing schema

Point bootstrap at your existing database:

pgmagmig bootstrap \
  --migrations-dir ./migrations \
  --from-database postgres://localhost/mydb

Or if you have your schema as SQL files:

pgmagmig bootstrap \
  --migrations-dir ./migrations \
  --from-sql schema.sql

This creates two files:

  • 0001.yaml — creates pgmagmig’s management table.
  • 0002.yaml — captures your entire existing schema.

2. Register the migrations in your database

Open 0001.yaml. At the top you’ll find a comment block with exact SQL to run:

CREATE TABLE public.schema_migrations (
  sequence integer PRIMARY KEY,
  uuid uuid NOT NULL,
  title text NOT NULL,
  down text
);

INSERT INTO public.schema_migrations (sequence, uuid, title, down) VALUES
    (1, '<uuid-from-0001>', 'Create pgmagmig management table', NULL),
    (2, '<uuid-from-0002>', 'Existing database schema', NULL);

The UUIDs in the comment match the ones in 0001.yaml and 0002.yaml.

Run this SQL against your database using whatever mechanism you currently use — your existing migration tool, a manual psql session, or a deployment script. This creates the pgmagmig management table and records both bootstrap migrations as already applied, which is correct: the management table now exists (from the SQL you just ran) and the rest of the schema was already there.

3. Verify the state

pgmagmig migrate \
  --migrations-dir ./migrations \
  --database-url postgres://localhost/mydb \
  --check

This should report “Database is up to date.” If it doesn’t, the schema in your database differs from what pgmagmig extracted — investigate before proceeding.

4. Clean up the old system (optional)

If your previous migration system had its own management table (e.g., schema_migrations from Rails, _prisma_migrations from Prisma, alembic_version from Alembic), you can now create a pgmagmig migration to drop it:

# Add the old table to your schema SQL as a reminder, then:
pgmagmig draft-migration \
  --migrations-dir ./migrations \
  --to-sql schema.sql \
  --title "Remove old migration table" \
  --allow-hazards all

Or write the migration by hand — it’s just a YAML file with DROP TABLE in the up field.

How it works

The two-migration bootstrap captures a clean baseline:

flowchart TB
  subgraph before ["Before: existing database"]
    direction LR
    old_tables["Your tables,\nindexes, etc."]
    old_mgmt["Old migration\ntable (optional)"]
  end

  subgraph bootstrap ["Bootstrap"]
    direction TB
    gen["pgmagmig bootstrap\n--from-database ..."]
    m1["0001.yaml\nCreate pgmagmig table"]
    m2["0002.yaml\nExisting schema snapshot"]
    gen --> m1
    gen --> m2
  end

  subgraph transition ["Transition SQL (run via old system or manually)"]
    direction LR
    create["CREATE TABLE\nschema_migrations"]
    insert["INSERT rows\nfor 0001 + 0002"]
    create --> insert
  end

  subgraph after ["After: pgmagmig manages the database"]
    direction LR
    tables["Your tables\n(unchanged)"]
    pgm_table["pgmagmig\nmanagement table"]
    future["Future migrations\nvia pgmagmig"]
  end

  before --> bootstrap
  bootstrap --> transition
  transition --> after

  style before fill:#3332
  style after fill:#5a52
  • Migration 1 is the management table itself. It exists so that pgmagmig can manage its own infrastructure through the same mechanism it manages everything else.
  • Migration 2 is a snapshot of the existing schema at the point of adoption. It has no down migration (down is omitted), because rolling back the entire existing schema is not meaningful.

From this point forward, all schema changes go through pgmagmig. The migration history starts clean, with a clear record of what the database looked like when pgmagmig took over.