Skip to main content

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.

PyPI Quality Gate Python 3.11+ PostgreSQL 12+ License: MIT


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: replay pending migrations on a parallel DB, emit a structural diff vs. db/schema/.
$ 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.


No db/schema/ directory? That works too.

confiture migrate up, down, status, baseline, and preflight are the migration runner — they don't require a db/schema/ directory. The "Build from DDL" pitch above the fold sells one of confiture's four strategies; the other three (incremental migrations, production sync, schema-to-schema FDW migration) work against a project whose only source of truth is the migration chain itself.

If you're evaluating confiture against Flyway / Alembic / dbmate / sqlx-cli as a pure migration runner, skip confiture build and use everything else. Walkthrough: docs/guides/02-incremental-migrations.md.


When to use Confiture?

Capability Confiture Flyway Alembic dbmate sqlx-cli plain psql
Source of truth DDL files or migration chain 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

Note on "source of truth": confiture can run as a pure migration tool against a project that has no db/schema/ directory — the DDL workflow is opt-in. See No db/schema/ directory? above.

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 have a migration chain (no db/schema/) and want preflight + tracking Confiture (use everything except confiture build)
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.

Migrations that open their own SAVEPOINTs, use psycopg's conn.transaction(), or wrap DO $$ … EXCEPTION WHEN … $$ blocks are supported under all three modes. The rules a migration body must follow for the SAVEPOINT-based rollback to stay clean are documented in the transaction & SAVEPOINT contract.


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

Guides

Reference

For agents and tooling

  • Every machine-readable CLI output has a published JSON schema under docs/reference/json-schemas/ — see docs/reference/json-schemas.md.
  • confiture migrate validate --list-patterns --format json exposes the full idempotency-detection catalog (read-only, no DB / config / migrations directory needed).
  • Quiet-success ambiguities surface advisory hints in payload["hints"] (or on stderr in text mode) — exit codes are unaffected.

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fraiseql_confiture-0.18.0.tar.gz (1.8 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

fraiseql_confiture-0.18.0-cp314-cp314-win_amd64.whl (922.3 kB view details)

Uploaded CPython 3.14Windows x86-64

fraiseql_confiture-0.18.0-cp313-cp313-win_amd64.whl (922.3 kB view details)

Uploaded CPython 3.13Windows x86-64

fraiseql_confiture-0.18.0-cp313-cp313-manylinux_2_28_x86_64.whl (1.0 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ x86-64

fraiseql_confiture-0.18.0-cp313-cp313-macosx_11_0_arm64.whl (968.8 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

fraiseql_confiture-0.18.0-cp312-cp312-win_amd64.whl (922.4 kB view details)

Uploaded CPython 3.12Windows x86-64

fraiseql_confiture-0.18.0-cp312-cp312-manylinux_2_28_x86_64.whl (1.0 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ x86-64

fraiseql_confiture-0.18.0-cp312-cp312-macosx_11_0_arm64.whl (968.8 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

fraiseql_confiture-0.18.0-cp311-cp311-win_amd64.whl (922.0 kB view details)

Uploaded CPython 3.11Windows x86-64

fraiseql_confiture-0.18.0-cp311-cp311-manylinux_2_28_x86_64.whl (1.0 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64

fraiseql_confiture-0.18.0-cp311-cp311-macosx_11_0_arm64.whl (969.1 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

File details

Details for the file fraiseql_confiture-0.18.0.tar.gz.

File metadata

  • Download URL: fraiseql_confiture-0.18.0.tar.gz
  • Upload date:
  • Size: 1.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","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

Hashes for fraiseql_confiture-0.18.0.tar.gz
Algorithm Hash digest
SHA256 aec63e5e50c1ded810e62b5c24a73a5667fd07d155caf43c101976b91efa551d
MD5 6051bb3854b33ed41022fbde8c37a080
BLAKE2b-256 1a4c2ab392983d1a47f8505121c723cff033310278f47fbe6a0992edfbcbcf12

See more details on using hashes here.

File details

Details for the file fraiseql_confiture-0.18.0-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: fraiseql_confiture-0.18.0-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 922.3 kB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","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

Hashes for fraiseql_confiture-0.18.0-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 3dc4ba50b66966c71c691caca5c53609e8d3cb349df5cb906e5b1185c1259c23
MD5 d058e633d807151c1cc8dfd048179c3f
BLAKE2b-256 a273c89d7003b106df62e42a4afa57b057a6ee91efacbf72e3896044d9e13b99

See more details on using hashes here.

File details

Details for the file fraiseql_confiture-0.18.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: fraiseql_confiture-0.18.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 922.3 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","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

Hashes for fraiseql_confiture-0.18.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 4a1ae0554f5304d64859322bee88aa9f6ab6c4e4ba7ffe79f94a1210482ad051
MD5 392dff24e54e8769a8169addbc19338a
BLAKE2b-256 4b8239ea9769f48ff887480f80ad99594e869d4cf0f5ee57b868b1280530b58c

See more details on using hashes here.

File details

Details for the file fraiseql_confiture-0.18.0-cp313-cp313-manylinux_2_28_x86_64.whl.

File metadata

  • Download URL: fraiseql_confiture-0.18.0-cp313-cp313-manylinux_2_28_x86_64.whl
  • Upload date:
  • Size: 1.0 MB
  • Tags: CPython 3.13, manylinux: glibc 2.28+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","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

Hashes for fraiseql_confiture-0.18.0-cp313-cp313-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ccd4de29383c684d35c19d949501cd2e0bb61dba442ac6aab7db973f1fa74654
MD5 d89e4ce8f8b6e08392eda4f73f5a9ef7
BLAKE2b-256 58fe27fdc453bbc0baeccecaf3b6e87a08fb6b92ae1730517b399f9ff7cbe388

See more details on using hashes here.

File details

Details for the file fraiseql_confiture-0.18.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

  • Download URL: fraiseql_confiture-0.18.0-cp313-cp313-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 968.8 kB
  • Tags: CPython 3.13, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","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

Hashes for fraiseql_confiture-0.18.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 48c1bc71b3bc960899d7ff7f4a450cb9d953cf7e654f48e5a7bb1a23a8bfae27
MD5 3d862d092f478c3d3ca065c7913e7468
BLAKE2b-256 8d75baaa8eb70c79627d0f58b87a1c943be8e55aedaa40ccd91cd58733e2c609

See more details on using hashes here.

File details

Details for the file fraiseql_confiture-0.18.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: fraiseql_confiture-0.18.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 922.4 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","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

Hashes for fraiseql_confiture-0.18.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 cfb714552992e866619175aca88e79f37d23c3555a381dd8ca7ef6c6655431a6
MD5 6a8132d0420bf3584f8b535878260f0f
BLAKE2b-256 d9f2ee219a5a2fdd175d4e0431234dabfeb69fb0b8b7900ebd2a50e6c9f03ba9

See more details on using hashes here.

File details

Details for the file fraiseql_confiture-0.18.0-cp312-cp312-manylinux_2_28_x86_64.whl.

File metadata

  • Download URL: fraiseql_confiture-0.18.0-cp312-cp312-manylinux_2_28_x86_64.whl
  • Upload date:
  • Size: 1.0 MB
  • Tags: CPython 3.12, manylinux: glibc 2.28+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","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

Hashes for fraiseql_confiture-0.18.0-cp312-cp312-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 bc7ce4e6469a034e2275e2303e517eaada588ab07009a1dcbeb3a899d447469a
MD5 f8819eece99eaaf0a287041028f26677
BLAKE2b-256 b3053190c8eb263d5ffe454737e1f1272b16955e3f5a73a43efb7dfdfcb3f85f

See more details on using hashes here.

File details

Details for the file fraiseql_confiture-0.18.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

  • Download URL: fraiseql_confiture-0.18.0-cp312-cp312-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 968.8 kB
  • Tags: CPython 3.12, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","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

Hashes for fraiseql_confiture-0.18.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b96fabf9e4bbc1cc92ef2d9d4568e16fc5d85902bb693dc4a068125286576f2c
MD5 b2fd428b992aca92eff16bb102d7dc1c
BLAKE2b-256 00571b8d62c87642a96a3eb0eb9520c2a5b3aaad84e97fd3485ed14b43afaa9d

See more details on using hashes here.

File details

Details for the file fraiseql_confiture-0.18.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: fraiseql_confiture-0.18.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 922.0 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","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

Hashes for fraiseql_confiture-0.18.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 f871f1dcde92aa21ba3bdded1d9a3015a2bab7b291bf5f0caf7915f76b5e3639
MD5 1d8ba0a3f6e5efc59199e709f7be46eb
BLAKE2b-256 be5bf26edd81d0eeb2aaa276b19e59ba6949c2305e3ca1167a84c9266870ea70

See more details on using hashes here.

File details

Details for the file fraiseql_confiture-0.18.0-cp311-cp311-manylinux_2_28_x86_64.whl.

File metadata

  • Download URL: fraiseql_confiture-0.18.0-cp311-cp311-manylinux_2_28_x86_64.whl
  • Upload date:
  • Size: 1.0 MB
  • Tags: CPython 3.11, manylinux: glibc 2.28+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","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

Hashes for fraiseql_confiture-0.18.0-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a8e785f8f4857902ba99338f98a90932881233b5df76ada0c660cd957a55f99c
MD5 dac4565b84f0b8cfcdcf01e3fd722228
BLAKE2b-256 4a432441c403c0d2aff0cbae8f86f840bd5f671bf842561b8d19112bdba18c78

See more details on using hashes here.

File details

Details for the file fraiseql_confiture-0.18.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

  • Download URL: fraiseql_confiture-0.18.0-cp311-cp311-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 969.1 kB
  • Tags: CPython 3.11, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","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

Hashes for fraiseql_confiture-0.18.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5d22df4f11970ae3d73c90306008ed206ff05efecc9cf66a8de3f7ce764efe4a
MD5 126dcc8325aeb2c403a721795bd72160
BLAKE2b-256 643f239d74120c0392707bc261e32694e7bf8ddcec149e4889a615b32b6b077a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page