Plain SQL gives polyglot teams one migration format
Dbmate keeps database changes in timestamped SQL files instead of tying them to an application framework. A Go service and a Python service can use the same command, directory layout, and schema history. The tool creates migrations, applies pending files in numeric order, records their versions, reports status, rolls back the latest change, waits for a server, and writes a complete schema.sql file for review or fast test setup.
Our checkout had 88 files, about 8,622 lines of source, and occupied 0.6 MB. That compact source tree supports PostgreSQL, MySQL, MariaDB, SQLite, ClickHouse, BigQuery, and PostgreSQL-dialect Spanner paths described in the README. Dbmate is also a Go library, and Go's embed package can place migration files inside an application binary. The command remains the simpler choice when several application languages share a database workflow.
Timestamp versions reduce branch collisions but do not prevent them
Migration filenames begin with a numeric version, normally a timestamp, followed by a description. Dbmate stores only that leading number in its migrations table. Renaming the descriptive part is safe, but changing an already-applied migration is not: the README tells users to roll it back first. Pending files run in numerical order, and the optional strict mode fails when a migration would be applied out of sequence.
The default behavior permits an older pending migration to run after newer ones when branches land out of order. Timestamp versions reduce the chance of two developers choosing the same number, yet they cannot determine whether independently written SQL remains valid in a changed schema. Teams should enable strict mode in CI and settle migration conflicts during review. The tool supplies ordering and bookkeeping; it cannot prove that two branches made compatible database decisions.
What happened when we ran it
Our sandbox installed 356 packages in 59 seconds, then built Dbmate in 83 seconds. The test step exited with code 1 after 16 seconds. Go test reported 12 passed and 5 failed out of 17. The final log lines showed successful packages for dbutil, BigQuery, ClickHouse, MySQL, and PostgreSQL before failures in the SQLite driver.
The SQLite tail named TestSQLiteDumpSchema and TestSQLiteFTS5Available, and the driver package failed after 2.265 seconds. The supplied log does not show enough evidence to assign a cause, so we will not blame a missing system package or a code defect. The useful result is narrower: commit b735560 did not pass its full test command in our fresh unprivileged Debian container with 3 CPUs and 8 GB of RAM.
Schema dumps silently depend on external client programs
Running up, migrate, or rollback normally refreshes db/schema.sql. Dbmate recommends committing that file so reviewers can see the complete resulting schema and test environments can load it without replaying every migration. The dedicated dump command can also pass extra arguments to PostgreSQL or MySQL dump utilities. This is valuable, but it is not implemented entirely inside the standalone binary.
Schema export requires pg_dump, mysqldump, or sqlite3 in PATH. The README says automatic dump steps can be silently skipped when the required program is missing; running dbmate dump exposes the executable-not-found error. That deserves a CI assertion because a successful migration command does not guarantee that schema.sql was refreshed. Client versions should also be at least as new as the database server version, according to the setup guide.
Database URLs are simple until driver rules diverge
Most installations pass DATABASE_URL directly or load it from .env. Credentials with special characters must be URL encoded. PostgreSQL defaults to TLS and may need sslmode=disable for local development. SQLite paths are local files, while some PRAGMA changes require transaction:false. ClickHouse supports native TCP and HTTP variants, plus cluster-related URL settings. BigQuery uses application default credentials unless connected to an emulator.
Spanner is narrower than the database list suggests. Only its PostgreSQL dialect is supported, PGAdapter must be running, DDL migrations require transactions to be disabled, and schema dumps do not work. That is enough for a specific deployment, but not general Spanner coverage. With 356 packages resolved in our source install, driver breadth also has a visible contributor cost even though ordinary users can download a single binary.
Rollbacks and nontransactional databases need deliberate SQL
Dbmate cannot infer a rollback. Each migration needs a migrate:down block if developers expect rollback or down to reverse it. Transactions default to enabled when a database supports them, and multiple sections in one migration file are allowed. Database operations such as certain SQLite PRAGMAs or Spanner DDL require opting out, which also changes the failure model.
Open issue 675 describes a ClickHouse migration where later failure left earlier statements applied and status reporting misleading, followed by rollback-order trouble. A related August 2026 pull request addressed how one migration version is recorded across multiple sections. Teams using a nontransactional engine should prefer small files, test failure halfway through each sequence, and document manual recovery. A happy-path up check is not enough evidence for that case.
Active releases make the failed run worth investigating
Dbmate v2.35.1 was released on August 26, 2026, minutes after the repository's recorded last push. GitHub showed 7,267 stars and 50 combined open issues and pull requests. Recent work included database wait behavior, PostgreSQL environment handling, multi-section migration recording, dump processing, and dependency updates. The combined open count is a queue size, not a count of confirmed defects.
The current release and August issue activity point to maintained software, while our 5 failed test groups keep the verdict conditional. PostgreSQL or MySQL teams can trial the prebuilt binary quickly and test migrations against disposable databases. SQLite users should reproduce the two named failures first. Dbmate is at its best when plain SQL and a common CLI matter more than automatic rollback generation or declarative schema reconciliation.

