Goose: SQL and Go Migrations, All in One Tool
If you've ever managed database migrations in a Go project, you know the pain. You either use a heavy ORM or piece together something custom. Goose sits in that sweet spot. It's a simple, focused migration tool that handles both plain SQL and Go-based migrations. No fuss, no magic. Just your database schema, under version control.
Originally built by Pressly, this project is mature and widely used. It integrates cleanly with your Go toolchain, supports multiple databases, and gives you the flexibility to write migrations however you like.
What It Does
Goose lets you define database schema changes in either raw SQL files or Go functions. You run goose up, and it applies pending migrations in order. You run goose down, and it rolls them back. It tracks which migrations have been applied in a goose_db_version table, so you don't accidentally run the same migration twice.
It supports PostgreSQL, MySQL, SQLite, and more. The core workflow is dead simple:
- Write a
.sqlfile with your migration (or a Go function). - Run
goose up. - Done.
Why It’s Cool
Here's what makes Goose stand out:
- Dual format support. Need a quick schema change? Write plain SQL. Need to backfill data or run complex logic? Write a Go migration. You can mix both in the same project without any friction.
- Embedded migrations. Since Goose is a Go binary, you can embed your migration files directly into your application binary. This means no external migration files to manage at deploy time. Just ship the binary and run migrations on startup.
- Clean migration state. It uses a single table to track history, making it easy to inspect or even manually fix state if something goes wrong.
- Go-based migrations give you full power. Want to call an external API during a migration? Need to transform data using Go's standard library? You can do it, all while keeping the migration under version control.
It's not hyped. It's just a solid, no-nonsense tool that respects your workflow.
How to Try It
Install it with Go:
go install github.com/pressly/goose/v3/cmd/goose@latest
Create a migration:
goose create add_users_table sql
That creates a timestamp_add_users_table.sql file. Edit it with your SQL:
-- +goose Up
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
-- +goose Down
DROP TABLE users;
Then run it:
goose postgres "user=postgres dbname=mydb sslmode=disable" up
For Go migrations, create a .go file with Up and Down functions. Goose automatically picks them up if you run the binary from your project root.
The full docs are on the GitHub repo.
Final Thoughts
Goose is one of those tools that just works. It doesn't try to be everything, and that's its strength. If you're building a Go service and need reliable database migrations without dragging in an ORM, this is a solid choice. Pair it with a good SQL linter and you've got a migration pipeline that's easy to reason about and hard to break.
Give it a shot on your next project. You might not need anything fancier.
Originally spotted on @githubprojects