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
      - 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
      # 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. pglast (PostgreSQL's own parser) comes with it since 0.50.0.

# pyproject.toml
[dependency-groups]
dev = [
  "fraiseql-confiture>=0.50",
  "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

  • JSON schemas are published for the --format json output of build, drift, introspect, lint, sync, validate-config, verify-checksums and, in the migrate family, migrate up, migrate down-to, migrate status, migrate current, migrate fix, migrate introspect, migrate preflight, migrate validate and migrate verify. They ship in the package (python/confiture/schemas/) and are mirrored under docs/reference/json-schemas/; a test asserts the mirror equals the packaged source (see docs/reference/json-schemas.md). The other commands' JSON payloads are stable but not schema-backed yet.
  • 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.54.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.54.0
File Size Uploaded
fraiseql_confiture-0.54.0.tar.gz 2.6 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for fraiseql-confiture 0.54.0
File
fraiseql_confiture-0.54.0-cp314-cp314-win_amd64.whl CPython 3.14 CPython 3.14 Windows x86-64 Details
fraiseql_confiture-0.54.0-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details
fraiseql_confiture-0.54.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.54.0-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
fraiseql_confiture-0.54.0-cp312-cp312-win_amd64.whl CPython 3.12 CPython 3.12 Windows x86-64 Details
fraiseql_confiture-0.54.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.54.0-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details
fraiseql_confiture-0.54.0-cp311-cp311-win_amd64.whl CPython 3.11 CPython 3.11 Windows x86-64 Details
fraiseql_confiture-0.54.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.54.0-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details

Total release size: 14.5 MB

Release files / fraiseql_confiture-0.54.0.tar.gz

Download URL fraiseql_confiture-0.54.0.tar.gz
Size 2.6 MB
Tags Source
SHA-256 checksum
How to use checksums
8b49ecf38434db8367128a911a78f7a0168eae84aa64ebc5721b2c5f11478298
BLAKE2b-256 checksum
How to use checksums
3204d752ac57a49d2f4a6818c488b5657938808a02c97e6df61c047ba5b61cf9
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.54.0-cp314-cp314-win_amd64.whl

Download URL fraiseql_confiture-0.54.0-cp314-cp314-win_amd64.whl
Size 1.1 MB
Tags CPython 3.14 Windows x86-64
SHA-256 checksum
How to use checksums
471e12c73490a880a43d61eea17050a7cb1eef761b7cbcda4d3b5fc459fb6216
BLAKE2b-256 checksum
How to use checksums
240ca2d4d89b5510de67ceeda543c1ef36cfead409ae45241cef695a3eca849f
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.54.0-cp313-cp313-win_amd64.whl

Download URL fraiseql_confiture-0.54.0-cp313-cp313-win_amd64.whl
Size 1.1 MB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
5c7fe7b61d1cf5a2043cd4f6a93e44c47fd05ab9b60915ba4148f811b0866e58
BLAKE2b-256 checksum
How to use checksums
f4b10408b59fe00ecb3583764a6b3b1441fc453eebc8b4b10a8d53ba8a5108cd
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.54.0-cp313-cp313-manylinux_2_28_x86_64.whl

Download URL fraiseql_confiture-0.54.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
75ca4072379fb9f693c5d0988ee88f7b31b80524244f2d705051c11de079663c
BLAKE2b-256 checksum
How to use checksums
d1878fb482a243a97a9063545f3e424910dc42d9a2011a53024ac9cca157c6e5
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.54.0-cp313-cp313-macosx_11_0_arm64.whl

Download URL fraiseql_confiture-0.54.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
f7eefc00b08d8ccc708d91905c66bfc612b6e73384deb5752cfc6ce179df258a
BLAKE2b-256 checksum
How to use checksums
eb3761513c60f5ecf9907e13906f66ad4658badb2a68522250e6c0ff13769d0a
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.54.0-cp312-cp312-win_amd64.whl

Download URL fraiseql_confiture-0.54.0-cp312-cp312-win_amd64.whl
Size 1.1 MB
Tags CPython 3.12 Windows x86-64
SHA-256 checksum
How to use checksums
32bd9b6addf0109ec67c9becbfeb602987e4ed624d921a7110569d5967b7f5ce
BLAKE2b-256 checksum
How to use checksums
41041532af472a0a51a857e42b6aaa94631620e8083e99f8e6d9acf8c20b3d5b
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.54.0-cp312-cp312-manylinux_2_28_x86_64.whl

Download URL fraiseql_confiture-0.54.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
99ea83bb87c5c4a927907699f57686ea7418c08b4857cc90e3b316741e37e49e
BLAKE2b-256 checksum
How to use checksums
cd2405550f920a55180db37b4e5ce68dc5a6753d7ab14754006fac8540e18f91
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.54.0-cp312-cp312-macosx_11_0_arm64.whl

Download URL fraiseql_confiture-0.54.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
7f1c9eb4150ea650dcb4bd73c104a7512eed44c72db3f3a6645e36a33ef3abc2
BLAKE2b-256 checksum
How to use checksums
3a46beb59a9ccc1f42e37eb8fd4ea3ba5cba4cba3a6964ba867329892ee27df5
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.54.0-cp311-cp311-win_amd64.whl

Download URL fraiseql_confiture-0.54.0-cp311-cp311-win_amd64.whl
Size 1.1 MB
Tags CPython 3.11 Windows x86-64
SHA-256 checksum
How to use checksums
dd2edd1f2f8a7e26199f28827dd451b3fb0733b9fac36810844f4df3f520814c
BLAKE2b-256 checksum
How to use checksums
faf4f1053f4744eecd192f5bbe76f4a2e9a742dac5f47e82cf6f602cb0e3910f
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.54.0-cp311-cp311-manylinux_2_28_x86_64.whl

Download URL fraiseql_confiture-0.54.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
e8910808871bedfefc1fc44ebb47752b0286e3ce0ae77e2e72a689b07375b407
BLAKE2b-256 checksum
How to use checksums
2c45136d8f771aa457d368e436a5903277f996343d5946094703fae17b5f1b99
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.54.0-cp311-cp311-macosx_11_0_arm64.whl

Download URL fraiseql_confiture-0.54.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
f47bc00449f74fd19206a3e327c4d707c6b8fd935ea63ce478851c006649824c
BLAKE2b-256 checksum
How to use checksums
28b7e4ff7d3b7fe448e8c9963375e35414cb030ceecca18556a49530ae9470f8
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.54.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