Stage 3 · Build
Databases & Persistence
Migrations
Manage schema changes with golang-migrate or goose, reversible migrations, and deployment ordering.
Why Migrations
Migrations version-control your database schema. Every schema change is a numbered file that can be applied, rolled back, and audited. Without migrations, schema drift between environments causes production incidents.
Migration Tools
| Tool | Language | Features |
|---|---|---|
| golang-migrate | Go | CLI + library, multiple databases, testing support |
| goose | Go | SQL-only, simple, supports Go migrations |
| atlas | Go | Declarative + versioned, lint, diff |
| flyway | Java/JVM | Enterprise, multiple languages, checksums |
golang-migrate is the standard choice for Go backends. It integrates with testcontainers for integration tests and supports PostgreSQL, MySQL, and SQLite.
Writing Migrations
Each migration is a numbered SQL file. Up migrations apply the change, down migrations reverse it. The migration tool tracks which migrations have been applied in a schema_migrations table.
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_users_email ON users(email);Number migrations sequentially. Include the extension creation in the first migration. Name files descriptively.
Reversible Migrations
Every up migration must have a corresponding down migration. Down migrations let you roll back broken changes. Always test both directions.
DROP TABLE IF EXISTS users;The down migration reverses the up migration. Drop tables, remove columns, or undo data changes. Test down migrations in staging before deploying.
Deployment Ordering
Migrations must be backward-compatible. The old code version must work with the new schema during rolling deployments. Never drop a column that old code still reads.
Dropping a column, renaming a table, or changing a column type breaks the running application. Use multi-phase migrations: add new, migrate data, remove old. Each phase is a separate deploy.
Migration Strategies
- Sequential: Run migrations as part of application startup. Simple but risky in multi-instance deployments.
- CI/CD pipeline: Run migrations in the deployment pipeline before starting new code. Safer with coordination.
- Migration service: Dedicated process that applies migrations. Prevents race conditions between instances.
- Blue-green: Apply migrations on the green environment before switching traffic. Zero-downtime rollback.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.