Common retrofit workflows

In these demos, developers author schema changes with retrofit, including refactorings such as RenameColumn and ExtractTable. From those changes, retrofit can render SQL for the environment it will run in, whether a developer’s laptop or a live production system.

Seed data is the data used to initialize the database instances that an application or a test suite runs against. A label identifies seed data, and multiple labels can be used to compose datasets for different scenarios or regression tests.

Exercised
data capture --label
snapshot --label
data scaffold --label
data check
RenameColumn
Stack
PostgreSQL + Docker + git
Chapters
4

Once a lookup table is declared as reference data, snapshot and migrate emit its rows as INSERT statements in the same script as its DDL, and the .sql side file that held them is retired. In the log, retrofit records the declaration, and data capture writes the rows to a data file pinned to it. A rename leaves the rows intact, and each data file is witnessed and sealed, so a hand edit to one fails validate.

Exercised
schema ref-tables
data capture
data scaffold
data witness
Seal
RenameTable
RenameColumn
Stack
PostgreSQL + git
Chapters
4

A Rails polymorphic association is a class name in a string column beside an id that points at more than one table, and no foreign key can hold it. When we want foreign keys on a populated table, strong_migrations stops the one-migration version and hands back five to write by hand, with a rollback nothing checks. We author that recipe as operations, retrofit renders each migration forward and in reverse, and Rails runs them the way it runs everything.

Exercised
import --ddl-only
identify --expect
migrate --down --strict
AddCheck
DropColumn
Stack
Rails 8.1 + strong_migrations 2.8 + PostgreSQL 17
Chapters
4

We have a handful of branches to review, each with a schema change, against a production-shaped snapshot we do not want to reload. Per branch, make db-up migrates the snapshot up, and after walking through the change we call make db-down to migrate it back. One branch would drop a column, which our policy forbids, so db-up stops it before anything runs. The two we could test are merged, and their combined migration runs against the snapshot as it will against production.

Exercised
identify --expect
migrate --down --strict
validate
reconcile
DropColumn
Stack
git + make + PostgreSQL
Chapters
4

Given a dump of the schema Liquibase built, retrofit imports it and renders the two migrations that add and validate a foreign key, and their rollbacks, from one operation log; Liquibase deploys them. One of those rollbacks runs nothing, because PostgreSQL cannot unvalidate a constraint.

Exercised
import
identify
AddForeignKey
ValidateConstraint
Stack
Liquibase + PostgreSQL
Chapters
5

A teammate adds a column to the operation log and pushes. We pull. Before the app runs, one Makefile check finds the local database behind the log, and make db-sync renders the migration from the database’s own dump.

Exercised
identify --expect
migrate --from-dump
AddColumn
Stack
make + git + PostgreSQL
Chapters
3

From a schema dump imported into its operation log, retrofit writes the migrations that add and then validate a foreign key between existing tables, then backs the change out and reapplies it. Every script is generated, none is written by hand.

Exercised
import
Seal
AddForeignKey
ValidateConstraint
Stack
Flyway + PostgreSQL
Chapters
4

From a schema-only dump of a database that has data in it, retrofit imports the schema as operations. The data stays in PostgreSQL through column and table refactors, and changes made directly in the database are read back into the log. The starting point can be a database dump, a set of migration scripts, or an empty log; this demo starts from the dump.

Exercised
import
identify
drift
ExtractTable
Seal
Stack
PostgreSQL
Chapters
4