>
dbwarden
/ migrate from alembic

Migrate from Alembic
to dbwarden.

Already using Alembic? Start here. Alembic keeps schema truth in a chain of revision scripts; dbwarden keeps it in the models and derives plain SQL migrations from them. Your models stay exactly where they are and your database is never rebuilt; you are replacing the migration workflow, not the schema. Alembic history stays in git, alongside the rest of your history.

Every Alembic concept has a dbwarden counterpart.

Alembicdbwarden
alembic.ini + env.pydbwarden.py config file
Revision script (.py)Migration file (.sql) with upgrade / rollback sections
Revision chain as source of truthSQLAlchemy models as source of truth
alembic revision --autogeneratedbwarden make-migrations "description"
alembic upgrade headdbwarden migrate
alembic downgrade -1dbwarden rollback
alembic stamp <rev>dbwarden migrate --baseline
alembic currentdbwarden status
alembic historydbwarden history
alembic upgrade head --sqlexport-models + make-migrations --offline

Two Alembic features have no direct equivalent, and it is worth knowing before you start: Python data migrations (dbwarden manual migrations are SQL) and revision branching and merging (dbwarden uses a linear versioned sequence per database).

Before and after.

In Alembic, a schema change is a revision script: a Python module with a revision id, a down_revision pointer, and upgrade and downgrade functions that call op.* builders. The chain of these scripts becomes the schema's effective definition.

In dbwarden the same change starts as a model edit, and the migration is the SQL derived from it, upgrade and rollback in the same file, generated from the same diff. Both sides below describe the same change: add a nullable bio column to users.

alembic revision
revision = "ae1027a6acf"
down_revision = "1975ea83b712"

def upgrade():
    op.add_column("users", sa.Column("bio", sa.Text()))

def downgrade():
    op.drop_column("users", "bio")
dbwarden model + artifact
class User(Base):
    bio = Column(Text, nullable=True)

-- upgrade
ALTER TABLE users ADD COLUMN bio TEXT;

-- rollback
ALTER TABLE users DROP COLUMN bio;

Six steps, none of them destructive.

01: Install and configure

uv add dbwarden, create dbwarden.py. This replaces alembic.ini and env.py. Model discovery is automatic; use model_paths to constrain it.

02: Generate the baseline

make-migrations "baseline from alembic" emits the full schema from your models. If the diff looks wrong, your models and database disagree; better to learn that now.

03: Baseline the database

migrate --baseline records the migration as applied without running it. This is the stamp equivalent.

04: Verify convergence

status, check, and diff must all be clean. If diff reports no differences, dbwarden and reality agree.

05: Offline CI (optional)

export-models, commit the state file, and drop the database service: make-migrations --offline from then on.

06: Retire Alembic

Remove alembic.ini, env.py, and versions/ from the active workflow. Replace alembic upgrade head with dbwarden migrate. The alembic_version table is inert.

Both tools can coexist during a transition period; they track state in separate tables. Generate the same change with both and compare the SQL until you are confident. Keep the overlap short.

the whole sequence
$ dbwarden init
$ dbwarden make-migrations "baseline from alembic"
$ dbwarden migrate --baseline
$ dbwarden status
$ dbwarden diff

What your team will notice.

The daily changes are mostly removals: no revision ids to invent, no down_revision chains to keep straight, no hand-written downgrade stubs. Four things stand out to a team coming from Alembic.

  • Renames are explicit. --rename users.name:full_name and --rename-table order:orders. A rename never silently becomes a drop-and-create.
  • Rollback is a contract. Executable rollback sits beside every upgrade; placeholder rollback is refused.
  • Table metadata moves into class Meta. Comments, advanced indexes, and backend options live on the model.
  • Destructive changes can be checked first. check-impact reports which code still references a column or table you are about to drop.
the flags
$ dbwarden make-migrations "rename name" --rename users.name:full_name
$ dbwarden make-migrations "pluralize" --rename-table order:orders

$ dbwarden check-impact 0002 --database primary
What happens to the existing Alembic history?

It stays in git, alongside the rest of your history. make-migrations "baseline from alembic" emits the full current schema from your models, and migrate --baseline records it as applied without running any DDL. The alembic_version table is left inert; nothing is rebuilt or dropped.

Can dbwarden and Alembic run side by side during the transition?

Yes. They track state in separate tables, so both tools can coexist. A common approach is generating the same change with both and comparing the SQL until you are confident; keep the overlap short.

Do the models have to change?

No. Your models stay exactly where they are; dbwarden reads them as the schema authority. Comments, advanced indexes, and backend options can move into class Meta, but that is optional and can happen incrementally.

What is lost by switching?

Python data migrations (dbwarden manual migrations are SQL) and revision branching and merging (dbwarden uses a linear versioned sequence per database). If either is central to your workflow, stay with Alembic.

Is the database ever rebuilt?

No. You are replacing the migration workflow, not the schema. migrate --baseline records the current schema as already applied without executing DDL, and generate-models can adopt an existing database into models when they were never written.

Stay with Alembic when

Python data migrations are central to your workflow, you rely on branching and merging revision graphs, or you want imperative control over every step.

Switch when

Most of your migrations are pure schema changes and you want models as the source of truth with SQL you review in the pull request.

New to dbwarden? See why models define the schema ↗dbwarden vs Alembic ↗The full migration guide ↗