Declare your desired database state in git. dbly makes it real.
dbly deploys your database objects — tables, views, functions, procedures, packages, triggers, grants — from version control to PostgreSQL, SQL Server, Oracle and SQLite. You keep one SQL file per object, like normal source code; dbly works out what changed and brings the target database in sync. Think Terraform for your database: declarative, predictable, repeatable.
Why
- Declarative — your repo is the source of truth. No hand-written migration chains, no version-number collisions on parallel branches.
- Plan before apply — preview exactly what will run, then execute. No surprises.
- Idempotent & safe — only the necessary changes are applied. Additive changes go automatically; destructive ones (dropping columns, etc.) are flagged and never run unless you explicitly allow them.
- Multi-database — one workflow across all four engines.
Install
uv sync # PostgreSQL + SQLite work out of the box
uv sync --extra oracle # add the Oracle driver
uv sync --extra mssql # add the SQL Server driver
uv sync --extra all # both
Organize your repo
One file per object; folder names map to database schemas. Use any extension you like
(.sql, .tbl, .vw, .prc, …) — dbly reads the SQL to know what each object is.
db/
sales/
customer.tbl
v_open_orders.vw
grants.sql
init/ # optional: privileged greenfield groundwork (CREATE DATABASE/ROLE…)
migrations/ # optional: ordered, run-once ALTERs for renames / data backfills
hooks/pre/ hooks/post/ # optional: .sql or .py hooks (e.g. ArcGIS/ArcPy steps)
.dbignore # files in the repo that should not be deployed
Most changes are declarative — edit the object file, dbly figures out the additive diff. For
changes the diff can't do safely (renaming a column, moving data), drop an ordered script in
migrations/ (0001_…sql); it runs exactly once, is recorded in the ledger, and the table
it touches defers to it for that deploy. On a fresh database, migrations are baselined
(recorded, not run) since the object files already describe the end state.
Connect
A connection profile (reuses the familiar connection.properties format):
environment=postgres # postgres | sqlserver | oracle | sqlite
service=db.example.com:5432
username=app
password=${DB_PASSWORD} # ${ENV} placeholders → keep secrets out of the repo (CI/CD-safe)
database=appdb
Use
# preview the changes between the deployed state and a git ref
dbly plan --to main --target prod.connection.properties
# apply them
dbly apply --to main --target prod.connection.properties
# export a plain SQL script to run by hand (e.g. through a customer VPN, no dbly needed)
dbly plan --to main --target prod.connection.properties --sql deploy.sql
# what is currently deployed?
dbly status --target prod.connection.properties
# has the database drifted from the desired state?
dbly check --target prod.connection.properties
# greenfield only: run privileged groundwork once under a superuser profile
dbly init --init-target super.connection.properties
Typical workflow: edit your object files → commit → dbly plan to review → dbly apply.
Deploying a subset of features is just choosing the git ref you deploy (a release tag or
branch). Destructive steps require --allow-destructive.
Built for trunk-based development
Database teams are usually locked out of trunk-based development: migration scripts collide on parallel branches, and "merge" effectively means "deploy to the customer". dbly is designed to break that deadlock for teams who write their logic in SQL, in the database:
- No migration numbers, no collisions. Two developers edit different objects — git merges them like any other code. Integrate early, every day.
- Merge ≠ deploy. The trunk is your desired state;
dbly apply --to <tag>ships the ref you choose, in the maintenance window you choose. Release what you want, when you want. - One trunk, every customer. dbly reads each database's real state, so customers on different versions are no problem.
Integrate continuously, deploy on your own schedule — trunk-based development, finally practical for state-based database developers.
Status
Early alpha — all four engines are implemented and tested against live databases.
License
MIT
Metadata
Release files for dbly 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| dbly-0.3.0.tar.gz | 1.5 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dbly-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.5 MB
Release files / dbly-0.3.0.tar.gz
| Download URL | dbly-0.3.0.tar.gz |
|---|---|
| Size | 1.5 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
298b50a0a559b79561f29439b1b821cc73df1375ed6aceeaa40c563b773f6634
|
|
BLAKE2b-256 checksum How to use checksums |
ca4fcf04f0d19161265dba4aa10055a615581e7db0259bdb9e621d433a87f6da
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.
Transparency logRelease files / dbly-0.3.0-py3-none-any.whl
| Download URL | dbly-0.3.0-py3-none-any.whl |
|---|---|
| Size | 42.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b1e7ced22870ecf3a0ae22f1b1650dcb8e35b1508edebc46b0fa57dbfb84c7a7
|
|
BLAKE2b-256 checksum How to use checksums |
f42fed2f2d85b50e39fb9207a48dffb13ceeb0a02a4bb524d23de590d4355ee7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.
Transparency log