PostgreSQL schema evolution with built-in multi-agent coordination 🍓
Project description
Confiture 🍓
PostgreSQL migrations, sweetly done.
Build from DDL. Adopt on day one against a database that already has migrations applied. Preflight every deploy against a parallel database with structural diff. Sync production data with PII anonymization.
In 30 seconds
# 1. You already have a database at migration 004 (applied by hand or by another tool).
# Tell Confiture about that history without re-running the SQL:
$ confiture migrate baseline --through 004 -c db/environments/production.yaml
✅ 001 create_users (marked as applied)
✅ 002 create_orders (marked as applied)
✅ 003 add_user_email (marked as applied)
✅ 004 add_user_preferences (marked as applied)
✅ Marked 4 migration(s) as applied, skipped 0 already applied
# 2. Machine-readable proof that the tracking is healthy:
$ confiture migrate status -c db/environments/production.yaml --format json | jq '.applied | length'
4
# 3. Preflight the next deploy end-to-end against a parallel database:
$ confiture migrate preflight --against "$PREFLIGHT_URL" -c db/environments/production.yaml
▸ Replaying pending migrations on preflight DB …
✓ 20260520143015_add_user_bio applied in 24 ms
▸ Comparing resulting schema vs. db/schema/ …
✓ No drift — preflight matches db/schema/
✓ Preflight passed. Safe to deploy.
exit 0
That's the loop. Baseline once → status to confirm → preflight every deploy.
Already have migrations?
The single biggest reason migration tools fail adoption is the day-one cliff: existing tables already exist, so any tool that tries to apply migrations from scratch crashes on the first CREATE TABLE. Confiture's answer is migrate baseline:
confiture migrate baseline --through <last-applied-version>
The walkthrough — including failure modes, the integration test that backs the recipe, and what tb_confiture ends up looking like — is in docs/guides/legacy-bootstrap.md.
When to use Confiture?
| Capability | Confiture | Flyway | Alembic | dbmate | sqlx-cli | plain psql |
|---|---|---|---|---|---|---|
| Source of truth | DDL files | migration chain | model classes | migration chain | migration chain | DDL files |
| Tracking table | yes | yes | yes | yes | yes | no |
Rollback (down.sql) |
yes | paid | yes | yes | yes | no |
| Preflight against a copy DB | yes (structural diff) | no | no | no | no | no |
| Build from scratch in <1s | yes | no | no | no | no | yes (manual) |
| Production sync + anonymization | yes | no | no | no | no | no |
| Zero-downtime via FDW | yes | no | no | no | no | no |
| Multi-agent coordination | yes | no | no | no | no | no |
| Ecosystem maturity / stars | early | very mature | mature | mature | mature | n/a |
Confiture wins on build-from-DDL, structural-diff preflight, production sync, and multi-agent coordination. It loses on ecosystem age — Flyway and Alembic have a decade of community knowledge. Pick honestly.
Adoption checklist
| Situation | Recommended tool |
|---|---|
| 1 environment + 1 contributor, schema rarely changes | plain psql |
| 2+ environments, schema changes weekly | Confiture, Flyway, Alembic, or dbmate |
| Multi-agent / AI-driven development on shared schemas | Confiture |
You want db/schema/ to be source of truth, not a migration chain |
Confiture |
You need zero-downtime schema swaps with postgres_fdw |
Confiture (Medium 4) |
| You're committed to SQLAlchemy ORM | Alembic |
| You're committed to a JVM stack | Flyway |
CI integration
A migrate preflight gate on every PR, a migrate up step on deploy. Exit codes are semantic, so the CI configuration stays simple:
# .github/workflows/db.yml
name: DB
on:
pull_request:
paths:
- 'db/**'
push:
branches: [main]
jobs:
preflight:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env: { POSTGRES_PASSWORD: x }
ports: ['5432:5432']
options: >-
--health-cmd pg_isready --health-interval 10s
--health-timeout 5s --health-retries 5
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v3
- run: uv pip install --system "fraiseql-confiture[ast]"
- name: Restore production snapshot to preflight DB
run: ./scripts/restore-snapshot.sh # your own; pg_restore from S3/GCS
- name: Confiture preflight
env:
PREFLIGHT_URL: postgresql://postgres:x@localhost:5432/preflight
run: |
confiture migrate preflight \
--against "$PREFLIGHT_URL" \
-c db/environments/preflight.yaml \
--format json --output preflight.json
- uses: actions/upload-artifact@v4
with:
name: preflight-report
path: preflight.json
deploy:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v3
- run: uv pip install --system "fraiseql-confiture[ast]"
- run: confiture migrate up -c db/environments/production.yaml
env:
DATABASE_URL: ${{ secrets.PROD_DATABASE_URL }}
Exit codes: 0 success, 2 config error, 3 SQL failure, 6 lock contention, 7 structural drift. See the dry-run guide for what each one means.
Python project snippet
Add Confiture as a dev dependency. The [ast] extra pulls in pglast for full PostgreSQL parsing — recommended for schemas with bulk seed data.
# pyproject.toml
[dependency-groups]
dev = [
"fraiseql-confiture[ast]>=0.9",
"pytest>=8",
]
# justfile
default:
just --list
db-build:
confiture build --env local
db-up:
confiture migrate up
db-status:
confiture migrate status
db-preflight:
confiture migrate preflight --against "$PREFLIGHT_URL"
Or as a Makefile:
db-build:
confiture build --env local
db-up:
confiture migrate up
db-status:
confiture migrate status
Library API
Confiture is a CLI first, but the migrator is fully usable from Python:
from confiture import Migrator
with Migrator.from_config("db/environments/prod.yaml") as m:
status = m.status()
if status.has_pending:
result = m.up()
print(f"Applied {len(result.applied)} migrations")
The Four Strategies
| Strategy | Use Case | Command |
|---|---|---|
| Build from DDL | Fresh databases, testing, CI | confiture build --env local |
| Incremental Migrations | Existing databases, production | confiture migrate up |
| Production Sync | Copy data with PII anonymization | confiture sync --from prod --anonymize users.email |
| Zero-Downtime | Complex migrations via FDW | confiture migrate schema-to-schema |
Documentation
Start here
- Getting started — first 5 minutes.
- Legacy bootstrap guide — adopting on an existing database.
- Prerequisites — PostgreSQL version, roles, secret stores.
Guides
- Build from DDL
- Incremental Migrations —
up,down, rollback. - Production Data Sync
- Zero-Downtime Migrations
- Dry-Run + Preflight
- Named Schemas
- Hooks
- Multi-Agent Coordination
Reference
Contributing
git clone https://github.com/fraiseql/confiture.git
cd confiture
uv sync --all-extras
uv run pytest
See CONTRIBUTING.md and CLAUDE.md.
Author & License
Vibe-engineered by Lionel Hamayon 🍓
MIT License — Copyright (c) 2025 Lionel Hamayon
Making jam from strawberries, one migration at a time. 🍓→🍯
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fraiseql_confiture-0.14.0.tar.gz.
File metadata
- Download URL: fraiseql_confiture-0.14.0.tar.gz
- Upload date:
- Size: 1.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
300157ff204fab5bfd76d55c2aba04b720a01aa4c7b9a54345d161d0136e3f76
|
|
| MD5 |
e32c4df9efafc74f80d85b608e35d322
|
|
| BLAKE2b-256 |
07bd2f56a429db9a145ce0bacc0aac7d1a2d87efb1eacc7c1c03e24e048ac3ab
|
File details
Details for the file fraiseql_confiture-0.14.0-cp314-cp314-win_amd64.whl.
File metadata
- Download URL: fraiseql_confiture-0.14.0-cp314-cp314-win_amd64.whl
- Upload date:
- Size: 865.9 kB
- Tags: CPython 3.14, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
331ad38444ebf7b1468f885e3bf2083b6b94e1445fa27fc8894a9f31c278d2fc
|
|
| MD5 |
57f301e070ff0735d8d5d83ef9120ded
|
|
| BLAKE2b-256 |
2f9bc576b2a5d8e18aa61c357d1517ba19b7b65a176bdfdded9e062cdb2cc462
|
File details
Details for the file fraiseql_confiture-0.14.0-cp313-cp313-win_amd64.whl.
File metadata
- Download URL: fraiseql_confiture-0.14.0-cp313-cp313-win_amd64.whl
- Upload date:
- Size: 865.9 kB
- Tags: CPython 3.13, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
edc3ec3cd6f721d6a8a27d73ab39a70cc7f67adefc14e1429211b990d220d3fd
|
|
| MD5 |
f7e71a3c15bee22ce2e17e1ac06d17b3
|
|
| BLAKE2b-256 |
258fe7de9157da1b872f80c3656d4d911dc4b5f40fdacfe2e45e2f636121f3af
|
File details
Details for the file fraiseql_confiture-0.14.0-cp313-cp313-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: fraiseql_confiture-0.14.0-cp313-cp313-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 958.3 kB
- Tags: CPython 3.13, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e282188837f38557af9f99fcfbb82d48b8fbb648bf7bda81185fa8a4870160e8
|
|
| MD5 |
6e03e63290df5a1c2de08eebf097dfb6
|
|
| BLAKE2b-256 |
a6394873895c819330eea3cb497f46441821de6ed5d78b23e55a83fbc270d350
|
File details
Details for the file fraiseql_confiture-0.14.0-cp313-cp313-macosx_11_0_arm64.whl.
File metadata
- Download URL: fraiseql_confiture-0.14.0-cp313-cp313-macosx_11_0_arm64.whl
- Upload date:
- Size: 912.7 kB
- Tags: CPython 3.13, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
67cdb58c02ecc555ebde3a194e1044b05805f2cefa94fffe6344fe44d143b448
|
|
| MD5 |
02f683b1eba88ad4d481e1a7fb7dcd89
|
|
| BLAKE2b-256 |
0cfbee811e1f56756290ed5fdca54a56eb23aca50b48c922a9a1034916f96444
|
File details
Details for the file fraiseql_confiture-0.14.0-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: fraiseql_confiture-0.14.0-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 866.0 kB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fcf28d49ea00b65a8b3f24657a7dad3e3302eaa415c444bed33dd0bef3178025
|
|
| MD5 |
ada6f8e65e204c18de9aef9b5a981fc0
|
|
| BLAKE2b-256 |
4029cf0f0958cb2ed96183f13ed24806186e19fe4b5dcbb52b7d22668f84757c
|
File details
Details for the file fraiseql_confiture-0.14.0-cp312-cp312-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: fraiseql_confiture-0.14.0-cp312-cp312-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 958.4 kB
- Tags: CPython 3.12, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6d03a626c94c31dd8ce6e54ca490a4afde8f95bf81ba0ad5d2c57c8659a5558
|
|
| MD5 |
dbbb96f4afcd05ff5c61c9c3121599b4
|
|
| BLAKE2b-256 |
318d1ae028588455b9234150a8fc93ac0f5e4ddae3d70d42d4e7b6ffb62d60ee
|
File details
Details for the file fraiseql_confiture-0.14.0-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: fraiseql_confiture-0.14.0-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 912.7 kB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8d0076bf591df46fd0884b101d3dba7563b1e1509e6535c26a70f154f149898f
|
|
| MD5 |
f200f03873caaeae2f0121f58a146b2b
|
|
| BLAKE2b-256 |
e5ec37d6f85ef3154e6b9561f640e3b300102b6d70f65031a9c1c7902659925f
|
File details
Details for the file fraiseql_confiture-0.14.0-cp311-cp311-win_amd64.whl.
File metadata
- Download URL: fraiseql_confiture-0.14.0-cp311-cp311-win_amd64.whl
- Upload date:
- Size: 865.8 kB
- Tags: CPython 3.11, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d76ac889bd976042a95ca523b59b05b936753cb743dea04f9898a41472172fd8
|
|
| MD5 |
3d8e52bee52df51190de53ddeadcca11
|
|
| BLAKE2b-256 |
87ee37f7c4d72d72d97eb7e24574a3171dc31adfdebecd94e8aea98be57a71f2
|
File details
Details for the file fraiseql_confiture-0.14.0-cp311-cp311-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: fraiseql_confiture-0.14.0-cp311-cp311-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 959.9 kB
- Tags: CPython 3.11, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2048ee36e42daf98de8b32176b28190bd52902bfb47071ca7be1904e424fc5f3
|
|
| MD5 |
2d4b39ffc0c606fda40c05b923549967
|
|
| BLAKE2b-256 |
be819a9b28499cb405145b8f12a52b9b483ac33af85c4312dbea91440c79cc25
|
File details
Details for the file fraiseql_confiture-0.14.0-cp311-cp311-macosx_11_0_arm64.whl.
File metadata
- Download URL: fraiseql_confiture-0.14.0-cp311-cp311-macosx_11_0_arm64.whl
- Upload date:
- Size: 913.0 kB
- Tags: CPython 3.11, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3a51a058c20acd18f5e856e66ff368b0c3f79e3a4028780d9661f58d91e0f9c6
|
|
| MD5 |
e709f07981ae0a5651141e9530537bf4
|
|
| BLAKE2b-256 |
258d486b992f5ec993b4336cb483d91e7e7a585692b4f771ea7de14a449043de
|