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, 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. 🍓→🍯

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

fraiseql_confiture-0.27.0.tar.gz (2.0 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.27.0-cp314-cp314-win_amd64.whl (963.3 kB view details)

Uploaded CPython 3.14Windows x86-64

fraiseql_confiture-0.27.0-cp313-cp313-win_amd64.whl (963.3 kB view details)

Uploaded CPython 3.13Windows x86-64

fraiseql_confiture-0.27.0-cp313-cp313-manylinux_2_28_x86_64.whl (1.1 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ x86-64

fraiseql_confiture-0.27.0-cp313-cp313-macosx_11_0_arm64.whl (1.0 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

fraiseql_confiture-0.27.0-cp312-cp312-win_amd64.whl (963.3 kB view details)

Uploaded CPython 3.12Windows x86-64

fraiseql_confiture-0.27.0-cp312-cp312-manylinux_2_28_x86_64.whl (1.1 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ x86-64

fraiseql_confiture-0.27.0-cp312-cp312-macosx_11_0_arm64.whl (1.0 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

fraiseql_confiture-0.27.0-cp311-cp311-win_amd64.whl (962.9 kB view details)

Uploaded CPython 3.11Windows x86-64

fraiseql_confiture-0.27.0-cp311-cp311-manylinux_2_28_x86_64.whl (1.1 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64

fraiseql_confiture-0.27.0-cp311-cp311-macosx_11_0_arm64.whl (1.0 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

File details

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

File metadata

  • Download URL: fraiseql_confiture-0.27.0.tar.gz
  • Upload date:
  • Size: 2.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","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.27.0.tar.gz
Algorithm Hash digest
SHA256 26cc3b5dcd27440b886b5621065a0abc929af298f2c7928668a1ba4b8ae34835
MD5 038ad172966e039920e6d39239eb9e6b
BLAKE2b-256 0b4241a39a78d7a661d4bef4e9be1122b9b58c95c1b136403eb730f7a04dd910

See more details on using hashes here.

File details

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

File metadata

  • Download URL: fraiseql_confiture-0.27.0-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 963.3 kB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","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.27.0-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 dc4b7aeec8bff7f555283c205edc2ecceb053a96fb9a77d5c76abda91f7cbec2
MD5 10e3e4ceda61338af8ea712348b27a61
BLAKE2b-256 9484978563d16f0dd614a6060b3796f1cfad797a8db78eccfb5f0eaa5c3b138b

See more details on using hashes here.

File details

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

File metadata

  • Download URL: fraiseql_confiture-0.27.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 963.3 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","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.27.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 343bd7a4c23dd9f2d27a9cc74f3e4d806035fab035ff9bf6a788ff1ccd00187c
MD5 e865540e0db16af9226d67ec6a2be80e
BLAKE2b-256 803a0051e3ad872eefb07a4043e8695b064a965f3d717482316b175b8b520672

See more details on using hashes here.

File details

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

File metadata

  • Download URL: fraiseql_confiture-0.27.0-cp313-cp313-manylinux_2_28_x86_64.whl
  • Upload date:
  • Size: 1.1 MB
  • Tags: CPython 3.13, manylinux: glibc 2.28+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","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.27.0-cp313-cp313-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b6dd40b73ab5b2e9f3d88ca7e1e4c226a65e5527abea46afee20df1a9c536062
MD5 065b0b290f2aab501111c8ea4b98c6a2
BLAKE2b-256 85954f14ab08b391911487e3c5deb8d5dce471664752a031a27d5e3d4ebc8ba9

See more details on using hashes here.

File details

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

File metadata

  • Download URL: fraiseql_confiture-0.27.0-cp313-cp313-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 1.0 MB
  • Tags: CPython 3.13, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","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.27.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2f81a4c83dc36faa265f57e6c186ed0b2188ac8df4459681d4622f4572e0abd7
MD5 62e1caabcb2bb40621b2d6686f966cc7
BLAKE2b-256 484282cb05973b1c77404d1b34e58dd9d4896d91c5e3bc6b02a359ea0e3f6023

See more details on using hashes here.

File details

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

File metadata

  • Download URL: fraiseql_confiture-0.27.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 963.3 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","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.27.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 88679bfd67fbb999fe50dcb8d38849c2b2f93ff373ef24efbbbee87a380f9b3a
MD5 80aa593059af8d70d6e1a10793305bb8
BLAKE2b-256 db37295c56424b02087be6d168491895d54c5e9ee906e57f4022b841bf03ece3

See more details on using hashes here.

File details

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

File metadata

  • Download URL: fraiseql_confiture-0.27.0-cp312-cp312-manylinux_2_28_x86_64.whl
  • Upload date:
  • Size: 1.1 MB
  • Tags: CPython 3.12, manylinux: glibc 2.28+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","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.27.0-cp312-cp312-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5b90e99bab5f4aa907ca3ed57fc9d6b7a504ea3a8ba61ba003d60c88b9548743
MD5 19d8e71242c90f5ab5cf6ff77735c089
BLAKE2b-256 4595343156a7694a91caef37dbf83134d578fbe21dbeb96e4fcc12d7a1e85afd

See more details on using hashes here.

File details

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

File metadata

  • Download URL: fraiseql_confiture-0.27.0-cp312-cp312-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 1.0 MB
  • Tags: CPython 3.12, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","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.27.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4f819a75108978801f0e5e97f116594dbaa17e12c9c66778ee7e0c93dbb70642
MD5 deb8e8a0e2f3f436429aea7e711c2417
BLAKE2b-256 fc3d3e4ff1dd8dece192eaf67d7a4c978aa6b7f265198042fc44b6303a73abad

See more details on using hashes here.

File details

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

File metadata

  • Download URL: fraiseql_confiture-0.27.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 962.9 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","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.27.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 ae3c88dd72defb99d14e6513b7e4c83cfea3884e2c5bed79660f3acb362a54e9
MD5 cd1b39c4e49d9e2ebc1421b897f330e5
BLAKE2b-256 36de0437dfdeda7e94a86aa533e2adab853044868465cf40c5821bbc72b45aaf

See more details on using hashes here.

File details

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

File metadata

  • Download URL: fraiseql_confiture-0.27.0-cp311-cp311-manylinux_2_28_x86_64.whl
  • Upload date:
  • Size: 1.1 MB
  • Tags: CPython 3.11, manylinux: glibc 2.28+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","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.27.0-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 90030dea800c29dd674e1abd1c614ad7c81b029a36f7718a737cb489327f89e8
MD5 52f4b4ff61253b6cf58d203ed0c0d8bc
BLAKE2b-256 a2b28e33801df178106ca5a7e3ce5309e316743ab3f1a8a071c39fbd4109769b

See more details on using hashes here.

File details

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

File metadata

  • Download URL: fraiseql_confiture-0.27.0-cp311-cp311-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 1.0 MB
  • Tags: CPython 3.11, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","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.27.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0537a7db420de21384be278b355f039725588498b07ce9c4e4b831616fc5229d
MD5 436144831dbf40d89cabefdc999bb7b4
BLAKE2b-256 747fc6f1e5fcafd5077320864cf23e1daec2344f5d7afabdc46fd679c5ce64f8

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