PostgreSQL · Hibernate · Kotlin · Gradle

Schema migrations you can prove.

MigAce migrates a database with real data and then proves the result is identical to the schema your application expects, down to the last constraint. No drift, no surprises in production.

# migrations/2026-11-11-add-customer-email.yaml
id: add-customer-email
parts:
  - sql: ALTER TABLE customer ADD COLUMN email text
  - data: UPDATE customer SET email = legacy_mail
  - sql: ALTER TABLE customer ALTER email SET NOT NULL

$ ./gradlew migaceVerify
✔ schema A  generated from Hibernate model
✔ schema B  restored from dump + 214 snippets applied
✔ A ≡ B     0 differences  (digest 9f3c…e1a7)
✔ HA check  compatible with release 4.12

The proof loop

Every build runs the same loop. If a migration doesn't produce exactly the expected schema on a database that already contains data, the build fails, long before production.

01 · TARGETGenerate schema A from your Hibernate model.
02 · RESTORELoad an older production-like dump with data into schema B.
03 · MIGRATEApply all pending snippets to B, part by part, fully logged.
04 · COMPAREDiff A and B: tables, columns, constraints, indexes, routines.
05 · SEALStore the schema digest. The app refuses to start on a mismatch.

Built for real enterprise databases

Born in a long-running Java EE project and rebuilt from scratch for PostgreSQL.

🎯

Zero-drift guarantee

Production schema matches the Hibernate-generated DDL exactly, verified on every build.

🔁

Re-runnable snippets

YAML snippets made of small parts. Each part is logged and skipped once applied, so a failed run simply resumes.

📦

Migrations on real data

Adding NOT NULL or unique constraints is tested against data, not just an empty schema.

🧮

Data migrations

First-class data and repair snippets, separate from schema changes and fully traceable.

🚦

HA & rolling updates

Classifies every change as compatible or breaking, so older app versions keep running during a Kubernetes rollout.

🔐

Schema digest at startup

The app checks a hash of the live schema and refuses to start against an unexpected database.

🧪

Test data generation

Generate realistic data for every new table and column so each snippet is exercised.

⚙️

Gradle-native

A Kotlin Gradle plugin with Testcontainers built in. One task: migaceVerify.

☸️

Runs where you deploy

Execute from an init container or job, or export a plain SQL script for your DBAs.

How MigAce compares

Indicative comparison for planned features. MigAce is not released yet.

CapabilityMigAceTypical versioned tools
Proves migrated schema = ORM modelYesManual / partial
Tests migrations against existing dataBuilt inUp to you
Resumable, part-level execution logYesPer-file
Rolling-update compatibility checkYesRare
Schema digest check at app startupYesRare

Get started (preview)

The plugin is not published yet. This is what using it will look like.

// build.gradle.kts
plugins {
    id("org.migace") version "0.1.0"
}

migace {
    database = postgres("17")
    snapshot = file("db/baseline.dump")
    snippets = file("db/migrations")
}