Skip to main content

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 Version Matrix Examples 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, down-to, status, current, baseline, and preflight are the migration runner — they don't require a db/schema/ directory (migrate current prints the latest applied revision as a narrow "what's deployed?" contract; migrate down --steps N rolls back relatively while migrate down-to <revision> rolls back to a specific revision, refusing atomically if any required .down.sql is missing). 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]"
      # No YAML needed in CI — the migrate family reads DATABASE_URL directly
      # (or pass --database-url "$DSN"). See the connection-source docs below.
      - run: confiture migrate up
        env:
          DATABASE_URL: ${{ secrets.PROD_DATABASE_URL }}

migrate up/down/status/verify/preflight accept --database-url <dsn> (or read CONFITURE_DATABASE_URL / DATABASE_URL) so runtime-resolved DSNs need no temp YAML — precedence and details in the CLI reference.

Exit codes are a documented stability contract — see the exit-code reference. The most operationally important: 2 tracking table absent, 3 DB connection failed, 5 config invalid, 6 lock contention. For migrate preflight's drift-gate codes specifically, see the dry-run guide.

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.
  • On an error path in --format json mode, the migrate family emits a structured error envelope on stdout — {"ok": false, "error": {code, message, severity, actionable, details, migration, file, line}} — and exits with the exit code for that error. The full code list and the envelope schema are in the error-code codebook.
  • 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. 🍓→🍯

Release files for fraiseql-confiture 0.48.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 fraiseql-confiture 0.48.0
File Size Uploaded
fraiseql_confiture-0.48.0.tar.gz 2.5 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for fraiseql-confiture 0.48.0
File
fraiseql_confiture-0.48.0-cp314-cp314-win_amd64.whl CPython 3.14 CPython 3.14 Windows x86-64 Details
fraiseql_confiture-0.48.0-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details
fraiseql_confiture-0.48.0-cp313-cp313-manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ x86-64 Details
fraiseql_confiture-0.48.0-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
fraiseql_confiture-0.48.0-cp312-cp312-win_amd64.whl CPython 3.12 CPython 3.12 Windows x86-64 Details
fraiseql_confiture-0.48.0-cp312-cp312-manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.28+ x86-64 Details
fraiseql_confiture-0.48.0-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details
fraiseql_confiture-0.48.0-cp311-cp311-win_amd64.whl CPython 3.11 CPython 3.11 Windows x86-64 Details
fraiseql_confiture-0.48.0-cp311-cp311-manylinux_2_28_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.28+ x86-64 Details
fraiseql_confiture-0.48.0-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details

Total release size: 14.2 MB

Release files / fraiseql_confiture-0.48.0.tar.gz

Download URL fraiseql_confiture-0.48.0.tar.gz
Size 2.5 MB
Tags Source
SHA-256 checksum
How to use checksums
ed77da391156387668037caddeb290098a822987e8f0e26316116ab4e4cd7557
BLAKE2b-256 checksum
How to use checksums
0696e8bea229c325613943afbec16ae5b32316ad1c93cd2a175e4fa5f279214e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","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 / fraiseql_confiture-0.48.0-cp314-cp314-win_amd64.whl

Download URL fraiseql_confiture-0.48.0-cp314-cp314-win_amd64.whl
Size 1.1 MB
Tags CPython 3.14 Windows x86-64
SHA-256 checksum
How to use checksums
a682f5497921c63bb3a4eb3e567caeaef2301ded7ebe051eb83a06404e49eca1
BLAKE2b-256 checksum
How to use checksums
7cb089f91d18336427531a4f81a6f4b84655ac117f2540acb035fd1aba7dd995
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","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 / fraiseql_confiture-0.48.0-cp313-cp313-win_amd64.whl

Download URL fraiseql_confiture-0.48.0-cp313-cp313-win_amd64.whl
Size 1.1 MB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
4751cb81cc5e6482639280c6a162e8214e7d91ff7de535572094e770d82a27e7
BLAKE2b-256 checksum
How to use checksums
4635680d6f5a34239ecae5e79216487fe72fea28a7f21d92f1002c27ed5267b1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","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 / fraiseql_confiture-0.48.0-cp313-cp313-manylinux_2_28_x86_64.whl

Download URL fraiseql_confiture-0.48.0-cp313-cp313-manylinux_2_28_x86_64.whl
Size 1.2 MB
Tags CPython 3.13 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
f4a0dc51923769d408763a3e3415806a90dcc8e82013a01666fda2ea15fd376e
BLAKE2b-256 checksum
How to use checksums
3444e322bc2d8594cbb88e08cdc9fa6f7838061ed48b74d964b9a072724fc582
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","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 / fraiseql_confiture-0.48.0-cp313-cp313-macosx_11_0_arm64.whl

Download URL fraiseql_confiture-0.48.0-cp313-cp313-macosx_11_0_arm64.whl
Size 1.2 MB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
a9771dbcdbcb4a61cf87f50bf1bb805e3cf4392181f7cdd9768e0b7f57e5ca1f
BLAKE2b-256 checksum
How to use checksums
a08768a3b48df32f46f1eee597f9d74b2eba059c1161610f3fdb3a4bbc53cdad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","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 / fraiseql_confiture-0.48.0-cp312-cp312-win_amd64.whl

Download URL fraiseql_confiture-0.48.0-cp312-cp312-win_amd64.whl
Size 1.1 MB
Tags CPython 3.12 Windows x86-64
SHA-256 checksum
How to use checksums
f93ff955cec95d3e4fea836ad140929677f4baae93ecfdeb7fc2d416a10153e5
BLAKE2b-256 checksum
How to use checksums
c8142092ba000de89bc0850dfcd8ebc50905c8483ac4e9334a7aecaf8e1f53e4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","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 / fraiseql_confiture-0.48.0-cp312-cp312-manylinux_2_28_x86_64.whl

Download URL fraiseql_confiture-0.48.0-cp312-cp312-manylinux_2_28_x86_64.whl
Size 1.2 MB
Tags CPython 3.12 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
9188821636ba1a93a0acb47a67ef42da0936c26b7eca690c09d17bb25ee64713
BLAKE2b-256 checksum
How to use checksums
9590dd78dcedb5ce8e1e3b524d97846a3d956fcf8ee5e11de7064a8052d0b8da
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","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 / fraiseql_confiture-0.48.0-cp312-cp312-macosx_11_0_arm64.whl

Download URL fraiseql_confiture-0.48.0-cp312-cp312-macosx_11_0_arm64.whl
Size 1.2 MB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
cfd32160c4a306734eedde1aa0fc825782b9c6faa1062ac5e581b99a4912815d
BLAKE2b-256 checksum
How to use checksums
33e58db86ae89dde0a4fb68a3c0b44a08b33320a2bbd77bbaa29553c6e13b1c9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","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 / fraiseql_confiture-0.48.0-cp311-cp311-win_amd64.whl

Download URL fraiseql_confiture-0.48.0-cp311-cp311-win_amd64.whl
Size 1.1 MB
Tags CPython 3.11 Windows x86-64
SHA-256 checksum
How to use checksums
f4ead3e8540d7624c9893113c0e3984a3e702bd9b7abe223cc1fdd43e3bc0818
BLAKE2b-256 checksum
How to use checksums
62789f8d401ef23a1e2478fa7b6ee0756c524ce06149b78e9de5d0fc1136eedd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","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 / fraiseql_confiture-0.48.0-cp311-cp311-manylinux_2_28_x86_64.whl

Download URL fraiseql_confiture-0.48.0-cp311-cp311-manylinux_2_28_x86_64.whl
Size 1.2 MB
Tags CPython 3.11 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
feb651df3d1684855b3c95c7a7541c33cecdbc2f082fe58bee537cbe5d0868d4
BLAKE2b-256 checksum
How to use checksums
20eec909bff4abaa7a21ce63607dd1159b68e1d3fe61bf6c2eed08625e85c4b1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","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 / fraiseql_confiture-0.48.0-cp311-cp311-macosx_11_0_arm64.whl

Download URL fraiseql_confiture-0.48.0-cp311-cp311-macosx_11_0_arm64.whl
Size 1.2 MB
Tags CPython 3.11 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
3df4741cbd144519ec534b0dee82bb9f96423116887306f1629ee0a7f2f9ceea
BLAKE2b-256 checksum
How to use checksums
52c681cfd7bb0c15af21f32188f5641510c79f01b29b87b080ea3d7efe49c4d1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","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

1.9.1

11 release files

1.9.0

11 release files

1.6.0

11 release files

This release

0.48.0 This release

11 release files

0.9.5

11 release files

0.9.4

11 release files

0.9.3

11 release files

0.9.2

11 release files

0.9.0

11 release files

0.8.9

11 release files

0.8.8

11 release files

0.8.7

11 release files

0.8.6

11 release files

0.8.5

11 release files

0.8.4

11 release files

0.8.3

11 release files

0.8.2

11 release files

0.8.1

11 release files

0.6.2

11 release files

0.6.0

11 release files

0.5.9

11 release files

0.5.8

11 release files

0.5.7

11 release files

0.5.6

11 release files

0.5.5

11 release files

0.5.4

11 release files

0.5.2

11 release files

0.5.1

11 release files

0.5.0

11 release files

0.4.4

11 release files

0.4.3

11 release files

0.4.2

11 release files

0.3.9

11 release files

0.3.7

10 release files

0.3.6

10 release files

0.3.5

10 release files

0.3.4

10 release files

0.3.2

10 release files

0.3.1

10 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