>
dbwarden
/ tool scope / state

Database Schema State
and Drift Detection.

Status, history, snapshots, diffs, and reverse engineering make the workflow observable: what is applied, what is pending, and whether the database actually matches the models. Schema drift is detected at generation time, before the next migration is written.

What is applied, and in what order.

status reports the applied and pending migrations for a database, which is the before-and-after pair you read around a deploy. history lists the full versioned sequence with applied state and timestamps, the audit trail for incident analysis: which migration ran, in what order, and when.

Both work per database in a multi-database repository, or across all of them with --all. Because each database keeps its own versioned sequence, the answers are always scoped to the database you ask about. After a Git merge, status can report MERGE_PENDING instead of allowing a new migration to be generated from an ambiguous base.

the commands
$ dbwarden status
$ dbwarden history --database primary
$ dbwarden status --all-environments
What is the difference between status and history?

status shows the applied and pending counts for the current state of a database; history lists the full versioned sequence with each migration’s applied state. Use status before and after a migrate, and history when you need the order.

Reproducible diffs from committed state.

After every migration, dbwarden writes a checksummed JSON snapshot of the schema to .dbwarden/schemas/. Generation diffs models against that snapshot or live state, so the same inputs produce the same SQL every time, and renames come out as renames rather than as a drop plus a create. The snapshot is what makes offline generation and deterministic diffs possible at all.

snapshot <table> prints the DDL of a single table, a quick way to read what the database actually holds for one object. diff compares models against the database or snapshot and shows structural differences without writing anything; generation is the step that produces files, so inspection stays read-only until you ask for output.

inspect the state
$ dbwarden snapshot users --database primary
$ dbwarden diff --format sql
What exactly is a schema snapshot?

A checksummed JSON capture of the full DDL state (tables, columns, types, indexes, constraints, enums), written to .dbwarden/schemas/ after each applied migration. It is the baseline for deterministic diffs and offline generation.

Is diff read-only?

Yes. diff shows structural differences between the models and the database or snapshot without writing anything. Generation is the step that produces files.

An existing database back to models.

generate-models reads a live database and writes SQLAlchemy models, so an existing schema can be adopted instead of rebuilt from scratch. It works across all supported databases; for ClickHouse it includes engine metadata automatically when database_type="clickhouse", and SQLite round-trips its own metadata (STRICT tables, generated columns, collations) in SqTableMeta / SqColumnMeta.

--base sets the declarative base the generated models inherit from, so generated code plugs into your existing model layout instead of introducing a second one. --tables and --exclude-tables scope the output, which matters for adopting a large legacy database incrementally, and --relationships generates relationship() attributes for foreign keys. Output is one file per table by default, or a single models.py with --single-file.

adopt an existing schema
$ dbwarden generate-models --base app.models.Base \
    --tables users,posts --database primary
Can generate-models replace a hand-written model file?

It produces one .py file per table by default, or a single models.py with --single-file. Use --base to inherit from your existing declarative base instead of generating a new one.

Can I adopt only part of a schema?

Yes. --tables and --exclude-tables scope which tables are introspected, so a large legacy database can be adopted incrementally instead of all at once.