Skip to content

Index

DBWarden

DBWarden

The SQL-first database toolkit for SQLAlchemy.

Python PyPI License DeepWiki

Full documentation  |  Source Code

DBWarden is a SQL-first migration system for Python and SQLAlchemy projects.

It is built for teams that want schema changes to remain explicit, reviewable, and operationally safe, from local development to production.

What DBWarden Does

  • Generates migration files as plain SQL, with -- upgrade and -- rollback sections
  • Reads SQLAlchemy models and backend-specific metadata from class Meta
  • Supports PostgreSQL, MySQL, MariaDB, SQLite, and ClickHouse
  • Manages one or many databases from one typed config source
  • Adds safety tooling, schema diffing, seed tracking, status commands, and FastAPI integration

The Core Workflow

DBWarden keeps the migration lifecycle simple:

  1. Define your models.
  2. Generate SQL from the model diff.
  3. Review the SQL file.
  4. Apply it with the CLI.
  5. Verify the result with status and history commands.
  6. Roll it back when you need to validate recovery.

Install

uv add dbwarden

Optional groups:

uv add "dbwarden[fastapi,metrics,sandbox]"

Quick Start

Step 1: Configure a database

Create dbwarden.py:

from dbwarden import database_config


primary = database_config(
    database_name="primary",
    default=True,
    database_type="postgresql",
    database_url_sync="postgresql://user:password@localhost:5432/main",
    model_paths=["app.models"],
    model_tables=["users", "posts"],
    dev_database_type="sqlite",
    dev_database_url="sqlite:///./development.db",
)

Step 2: Define your models

from datetime import datetime
from sqlalchemy import DateTime, ForeignKey, Integer, String, Text
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from dbwarden.databases import IndexSpec, TableMeta


class Base(DeclarativeBase):
    pass


class User(Base):
    __tablename__ = "users"

    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    email: Mapped[str] = mapped_column(String(255), unique=True, nullable=False)
    bio: Mapped[str | None] = mapped_column(Text, nullable=True)

    class Meta(TableMeta):
        comment = "Core user accounts"


class Post(Base):
    __tablename__ = "posts"

    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    title: Mapped[str] = mapped_column(String(255), nullable=False)
    body: Mapped[str] = mapped_column(Text, nullable=False)
    user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), nullable=False)
    created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)

    class Meta(TableMeta):
        indexes = [
            IndexSpec(name="ix_posts_created_at", columns=["created_at"]),
        ]

Step 3: Generate a migration

$ dbwarden make-migrations "create core tables" --database primary
Created migration: migrations/primary/primary__0001_create_core_tables.sql

Step 4: Apply it

$ dbwarden migrate --database primary
Applying migration: primary__0001_create_core_tables.sql
Migration applied successfully

Step 5: Verify the state

$ dbwarden status --database primary
Database: primary
Applied migrations: 1
Pending migrations: 0

Why Teams Use It

  • SQL remains the source of truth
  • Rollback SQL is part of the workflow, not an afterthought
  • Multi-database projects stay under one migration tool
  • Safety tooling is built in, not bolted on later
  • FastAPI projects can use the same config for sessions, health checks, and migration endpoints

Requirements

  • Python 3.12 or higher
  • SQLAlchemy models for model-driven migration generation
  • A supported backend: PostgreSQL, MySQL, MariaDB, SQLite, or ClickHouse

Next Steps