Skip to main content

db2md

CI Python 3.14+ License: MIT

One URL in. Schema docs out.

Database → db2md → Markdown → Mermaid ER

Database  →  db2md  →  Markdown  →  Mermaid ER

Connect with any SQLAlchemy URL. Discover databases. Introspect tables, FKs, indexes, and comments. Write one Markdown file per database with a Mermaid ER diagram — no hardcoded names, no config file.

pip install 'db2md[postgres]'
db2md --url 'postgresql+asyncpg://user:pass@localhost:5432/postgres'
# → ./schemas/<database>.md

Full documentation: edwinalkins.github.io/db2md

MkDocs integration: generate into docs/schemas/ then enable Mermaid superfences — see docs/integrate-mkdocs.md.

Why db2md?

Async-native SQLAlchemy 2.x + async drivers (asyncpg, aiomysql, aiosqlite)
Zero hardcoding Everything comes from introspection
Docs you can commit Markdown + Mermaid — preview on GitHub, MkDocs, Notion…
Library + CLI Script it, or run db2md in CI

Install

pip install 'db2md[postgres]'   # or [mysql] / [sqlite] / [all]

# From this repo
uv sync --extra postgres
Dialect Extra Driver
PostgreSQL postgres asyncpg
MySQL / MariaDB mysql aiomysql
SQLite sqlite aiosqlite

CLI

# List databases (skips system catalogs by default)
db2md --url 'postgresql+asyncpg://user:pass@localhost:5432/postgres' --list

# Document every non-system database → ./schemas/<db>.md
db2md --url 'postgresql+asyncpg://user:pass@localhost:5432/postgres'

# Specific databases / output path
db2md \
  --url 'postgresql+asyncpg://user:pass@localhost:5432/postgres' \
  -d myapp -d analytics \
  -o ./docs/db

uv run db2md --url 'sqlite+aiosqlite:///./app.db' -o ./schemas

Options

Flag Description
-u, --url SQLAlchemy URL (or set DATABASE_URL)
-o, --output Output directory (default: schemas/), or a file when documenting a single -d
-d, --database Database to document (repeatable). Default: all non-system DBs
--schema Schema/namespace (default: dialect-specific — public for PostgreSQL)
--er-style Mermaid ER attribute style: compat (default), optional, minimal
--list List databases and exit
--include-system Include system databases
-v, --verbose Debug logging
--version Show version

Bare dialects are upgraded to async drivers automatically (postgresql://… → postgresql+asyncpg://…, etc.).

Library API

import asyncio
from db2md import list_databases, generate_schema_markdown, export_schemas

URL = "postgresql+asyncpg://user:pass@localhost:5432/postgres"

async def main() -> None:
    dbs = await list_databases(URL)
    name, table_count, md = await generate_schema_markdown(URL, "myapp")
    paths = await export_schemas(URL, "schemas")
    print(dbs, name, table_count, paths)

asyncio.run(main())

Public symbols

Symbol Role
list_databases(url, *, include_system=False) List database names (dialect-aware)
generate_schema_markdown(url, database, *, schema=None) Returns (name, table_count, markdown)
export_schemas(url, output="schemas", …) Write one .md file per database
ColumnInfo / ForeignKeyInfo / IndexInfo / CheckConstraintInfo / TableInfo Introspection dataclasses

Output

Each generated file contains:

  1. ER diagram — Mermaid erDiagram with PK/FK markers and cardinalities inferred from the constraints (1–0..1, 1–0..N, N–N)
  2. Tables — columns, nullability, defaults, primary keys, comments
  3. Foreign keys, unique constraints, check constraints (name + SQL), indexes (columns + UNIQUE)

Example sketch:

# Database schema — `myapp`

> Auto-generated on 2026-08-02 12:00:00 UTC (schema `public`, 2 table(s)).

## ER diagram

```mermaid
erDiagram
    "users" {
        INTEGER id PK "Primary key"
        VARCHAR(255) email
    }
    "notes" {
        INTEGER id PK
        INTEGER user_id FK
        TEXT body "nullable"
    }
    "users" ||--o{ "notes" : "notes_user_id_fkey"
```

## Tables

### `users`

Application users

| Column | Type | Nullable | Default | PK | Comment |
|---|---|---|---|---|---|
| `id` | `INTEGER` | no | — | yes | Primary key |
…

Dialect behaviour

Backend Database discovery Default schema
PostgreSQL pg_database (non-template) public
MySQL / MariaDB SHOW DATABASES current catalog
SQLite single file DB n/a
Other current database only dialect-dependent

System databases skipped by default:

  • PostgreSQL: postgres, template0, template1
  • MySQL / MariaDB: mysql, information_schema, performance_schema, sys

Limitations

  • Views, materialized views, and sequences are not documented yet (base tables only).
  • Mermaid cardinalities are inferred from UNIQUE/PK constraints and FK nullability (junction tables → N–N). Details: docs/mermaid-cardinalities.md.
  • Under SQLite, -d / --database does not switch files (one DB per path); a warning is logged.

Development

uv sync --all-extras --group dev
uv run ruff check src tests
uv run mypy src
uv run pytest

# Docs
uv sync --group docs
uv run mkdocs serve

See CONTRIBUTING.md.

License

MIT © edwinalkins

Metadata

Release files for db2md 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for db2md 1.0.0
File Size Uploaded
db2md-1.0.0.tar.gz 3.9 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for db2md 1.0.0
File Interpreter ABI Platform
db2md-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 3.9 MB

Release files / db2md-1.0.0.tar.gz

Download URL db2md-1.0.0.tar.gz
Size 3.9 MB
Tags Source
SHA-256 checksum
How to use checksums
2cd9ddcfda3dd245ac32f2fcd0d1b8431f7467d9cd4709b8b86f2c7d917eff74
BLAKE2b-256 checksum
How to use checksums
9a783ce85aa11b4b85bbe04c6cf8e7791a189db7c6cf2bf742e5d37b5292c3ea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / db2md-1.0.0-py3-none-any.whl

Download URL db2md-1.0.0-py3-none-any.whl
Size 17.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3082faaffde0fb7755438be0abfa7db04883ebb5302b412198a08c99f026543d
BLAKE2b-256 checksum
How to use checksums
768a4345f7899586a2303eaf766e86d033dffe718925700312c5bf8211599359
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page