dbmap
Migration management tool for PostgreSQL
The problem
dbmap is a small CLI for Postgres developers who write their own SQL and only want ordered, tracked application of migrations. I built it in 2024 while learning Go, as a project with real edges rather than a toy.
The README puts it plainly: dbmap is not a SQL generator.
Key decisions
Track state in the database. There’s no schema diffing and no dependency graph. dbmap records what ran in two tables: one holds each migration’s name, time and status (pending or applied), and the other stores the exact SQL that was executed. That keeps the tool simple and the history auditable. “Map” refers to mapping migration files to their state in the database.
Plain SQL folders. Each migration is a folder with an up.sql and a down.sql. There’s no DSL to learn and no lock-in. It’s a single Go binary with no ORM and no runtime to install.
The commands today are init, create-migration and apply-migrations (up only), with integration tests for the first two using dockertest.
Tradeoffs
The ledger is simple, but it isn’t safe yet:
- Applying isn’t atomic. The migration SQL, the status update and the history insert are three separate calls, so a crash between them leaves inconsistent state.
- No locking. Two concurrent runs can apply the same migration.
- No checksums. Editing an already-applied file goes unnoticed.
initis destructive if re-run. It drops the status type withcascade, wiping tracking state.- Down migrations are stubbed: the files are scaffolded but never executed.
- Testability. Some utilities call
os.Exit, which makes them hard to test, andapply-migrationshas no tests.
If I redid it, I’d wrap each migration in one transaction, take a pg_advisory_lock, and store a hash of every file.
Outcome
Nothing shipped beyond the repo. It was a learning project, worked on between March and April 2024, and it taught me Go project layout, cobra, and testing against real databases in containers.