All demos/ Pull and sync
DEMO-03-SYNCSEP 2026
Retrofit stops the app before it runs against the wrong schema.
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.
- Stack
- make + git + PostgreSQL
- Change
AddColumnby pull,driftby hand- Reverse
- none; the gate is read-only
Chapters
make run checks the database against the log before the app starts. Today it passes. After the pull, it stops.
02
The database catches up from its own dump27 secmigrate --from-dump renders the one ALTER from the database’s own dump. make db-sync pipes it to psql, and make run passes.
03
Run it end to end47 secmake run passes, a git pull brings a teammate’s AddColumn, make run stops, make db-sync fixes it, and make run passes again.Summary
You pull teammates’ code and schema changes every day, and the local database is the one thing the pull does not update.
git pull updates the code and the operation log beside it. It cannot update
the local database. So the team’s run target checks first: a schema-only
pg_dump, and identify reports where in the log that schema is from. At the
head, the app starts. Behind it, expect-mismatch, and the make target that
fixes it.
git pull that carries a schema change, make run exits 2 before
the app starts, reports the version the database is at and the operation the
log has after it, and make db-sync migrates the database there from its own
dump. No history table is consulted. pg_dump reads the database, and
retrofit reads the dump.The dump is retrofit’s only input; it never connects to a database. psql
applies what migrate emits, make is the gate, and git carries the log.
Below is the team’s Makefile in full, the file the recordings run. The gate
is the two lines under check-db, and db-sync is the fix.
The team's Makefile
# The team's Makefile. Two targets matter here.
#
# make run check the local database against the operation log,
# then start the app
# make db-sync update the local database to the head of the log
#
# check-db is the whole idea. It is an ordinary prerequisite of run, so the
# check happens on every run without anyone remembering to do it. It costs
# one schema-only dump and one Retrofit command, and it stops with
# expect-mismatch when a pull updated the log and the database is behind
# it. The fix is make db-sync.
#
# Retrofit reads the dump. pg_dump and psql are what touch the database.
# -q drops Retrofit's note tier; warnings and errors still print, and
# nothing here filters or rewords them.
DB ?= postgres://postgres@localhost:55437/shop
SCHEMA ?= shop
.PHONY: run check-db db-sync
run: check-db
./bin/app "$(DB)"
check-db:
pg_dump --schema-only --schema=$(SCHEMA) "$(DB)" > .db.dump.sql
retrofit identify .db.dump.sql --expect last -q
db-sync:
pg_dump --schema-only --schema=$(SCHEMA) "$(DB)" > .db.dump.sql
retrofit migrate --from-dump .db.dump.sql -q | psql "$(DB)" -v ON_ERROR_STOP=1 -q
Chapter 01A git pull leaves the local database behind
How do we find out the local database is behind the log?
make run passes: the database matches the log and the app starts. A teammate added one AddColumn to the log, in the same commit as the code that reads it, and git pull brings both. make run now exits 2 with expect-mismatch before the app can fail on the missing column. The database is at v1, the log has the teammate’s operation after it, and the hint names the migrate command that renders the migration.Read transcript
pull-and-sync-demo: pull
Generated from the demo script. Every command below is run verbatim by the recording.
1/3 before the pull
an orders service. its schema is an operation log in git, beside the code. make run checks our database against that log before it starts the app:
make run
2/3 a teammate pushes, we pull
a teammate added a column to orders, changed the app to read it, and pushed. we pull:
git pull -q && git show --stat --oneline HEAD
the schema change came with the code, as one operation in the log:
retrofit op show -q | cut -c1-72
3/3 make run stops
our database does not have that column. the app would fail on its first query, so make run checks first:
make run
exit status 2
exit 2, before the app started. identify read a schema-only dump of our database and reported where in the log it is: v1, with the teammate’s operation after it. the hint is the command that renders the migration.
check-dbis a prerequisite ofrun. It takes a schema-only dump of the database, andidentifyreports where in the log that schema is from. Today that is the head, so the app starts.A teammate added one
AddColumnto the log, in the same commit as the code that reads it, and the pull brings both. The database on our laptop does not have it yet.The log was updated and the database was not.
identifyreports the database is at v1 and the updated log has the teammate’s operation after it.check-dbexits 2 before the app starts, withexpect-mismatchand themigratecommand that renders the migration.
Chapter 02The database catches up from its own dump
How does the local database catch up with the log?
make run is still stopping. The hint names migrate --from-dump, which renders the migration script that updates the database to the current version of the log, reading where the database is from the dump rather than from a history table. One ALTER. make db-sync renders it again and pipes it to psql. The same check passes, and the app reads its new column.Read transcript
pull-and-sync-demo: sync
Generated from the demo script. Every command below is run verbatim by the recording.
1/3 still behind
we pulled a teammate’s commit: a column added to orders, as one operation in the log, and the app changed to read it. our database does not have it, so make run stops before the app can fail:
make run
exit status 2
2/3 the migration
the hint names migrate –from-dump. it reads where our database is from the dump, not from a history table, and renders the script that updates it to the current log:
retrofit migrate --from-dump .db.dump.sql -q
one statement.
3/3 sync and run
db-sync renders the same script from the same dump and pipes it to psql:
make db-sync
the same check now passes, and the app reads its new column:
make run
Nothing has changed since the pull.
make runexits 2 again withexpect-mismatch, and its hint names themigratecommand that renders the migration.migraterenders the migration script that updates the database to the current version of the log.--from-dumpreads where the database is from the dump, not from a history table. OneALTER TABLE, and nothing else.make db-syncrenders the same script from the same dump and pipes it topsql.make runpasses, and the app reads its new column.
Chapter 03Run it end to end
make run passing, pull a teammate’s AddColumn with the code that reads it, watch make run exit 2 before the app starts, read the one ALTER that migrate --from-dump renders, run make db-sync, and watch make run pass with the app reading its new column.Read transcript
pull-and-sync-demo: complete walkthrough
Generated from the demo script. Every command below is run verbatim by the recording.
before the pull
an orders service. its schema is an operation log in git, beside the code. make run checks our database against that log before it starts the app:
make run
a teammate pushes, we pull
a teammate added a column to orders, changed the app to read it, and pushed. we pull:
git pull -q && git show --stat --oneline HEAD
the schema change came with the code, as one operation in the log:
retrofit op show -q | cut -c1-72
make run stops
our database does not have that column. the app would fail on its first query, so make run checks first:
make run
exit status 2
exit 2, before the app started. identify read a schema-only dump of our database and reported where in the log it is: v1, with the teammate’s operation after it. the hint is the command that renders the migration. no history table was consulted: pg_dump read the database, and identify read the dump.
sync and run
the hint names migrate –from-dump. first, the script it renders:
retrofit migrate --from-dump .db.dump.sql -q
one statement. db-sync renders it from the same dump and pipes it to psql:
make db-sync
the same check now passes, and the app reads its new column:
make run
a git pull updated the log and left our database behind it. one check said so before the app ran, and one command brought it up to date.