Native Hibernate JSON cutover
This release stores five String fields as PostgreSQL text:
- Authentication event details.
- Previous and new configuration snapshots.
- GitHub project field options.
- Connection audit detail.
Typed JSON data remains jsonb.
Hibernate uses the application-configured Jackson 3 mapper for that data.
HTTP and CSV authentication details and configuration snapshots remain Strings.
Both audit consoles retain their String contracts.
Prepare the upgrade
CAUTION: The previous binary cannot reliably read the new TEXT columns. TEXT cannot identify whether an old value was a JSONB String or a structured JSON value. Use a verified backup to recover the previous schema and data.
- Schedule an outage for all runtime roles:
server,worker, andwebhook. - Stop every replica of all three runtime roles.
- Stop external database writers and scheduled database maintenance.
- Confirm that no writer or old application process can restart during the migration.
- Create a complete database backup with the existing Liquibase history.
- Verify restoration of that backup in an isolated database.
- Check free disk space for table rewrites and WAL growth.
- Check that the migration role owns the affected tables, partitions, and pg_partman template.
The migration takes exclusive table locks and rewrites affected tables, including authentication partitions. Lock waits, table size, and WAL volume can extend the outage. Measure these costs on a restored database before production. Liquibase also holds its changelog lock. Do not remove a changelog lock while a migration process is active.
The migration refuses unexpected source column types or an incompatible authentication partition layout. It also refuses a missing pg_partman configuration or an incompatible configured template. Investigate a refusal before retrying. Do not mark the migration as complete manually.
Apply the release
-
Keep all runtime roles and other database writers stopped.
-
Use the verified target image's bundled Liquibase CLI to run
updatewith theprodcontext. Use the protected defaults file, runtime-user permissions, database network, and read-onlystatuscheck from the baseline runbook. Runupdate, not baseline synchronization:docker run --rm --network "$DATABASE_NETWORK" \--mount "type=bind,src=$LIQUIBASE_DEFAULTS_FILE,dst=/run/secrets/liquibase.properties,readonly" \--entrypoint /cnb/lifecycle/launcher "$TARGET_IMAGE" -- \java -cp 'runner.jar:lib/*' liquibase.integration.commandline.Main \--defaultsFile=/run/secrets/liquibase.properties --changeLogFile=db/master.xml \--contexts=prod update -
Confirm that Liquibase completed the migration and released its changelog lock.
-
Confirm TEXT types on all five columns, authentication partitions, and the configured pg_partman template.
-
Confirm that partition maintenance can create a future authentication partition.
-
Only after the migration completes, deploy the same new release to every runtime role through the normal deployment procedure.
-
Restart the runtime roles together after the migration completes.
-
Restore scheduled database maintenance and other database writers.
-
Check readiness and authorized audit reads.
The migration uses native ALTER COLUMN TYPE operations.
It does not update audit rows or disable audit guards.
Authentication redaction and configuration erasure remain available.
Configuration retention still permits deletion after 365 days.
Authentication retention still removes old partitions.
Check person-data exports
The release migration entry owns the person-data export change. Check consumers that read the affected fields. Parse a String as JSON only where the consumer requires that structure.
Recover the previous release
- Stop every replica of
server,worker, andwebhook. - Stop other database writers and scheduled database maintenance.
- Restore the verified database backup from before the cutover.
- Deploy the previous release to every runtime role.
- Restart the previous release against the restored database.
- Check readiness, audit reads, and export consumers.
Recovery discards writes made after the backup unless you recover them through a separately verified procedure. Liquibase rollback stops with a backup requirement. Do not reverse the TEXT conversion by casting values to JSONB. Do not start the previous binary against the converted database.