A YAML-first database migration tool that generates Goose-compatible migration files from declarative YAML schema definitions. Build database-agnostic schemas that automatically convert to database-specific SQL migrations.
The YAML schema format is the primary interface for makemigrations. It provides:
- ποΈ Database-agnostic: Write once, deploy to PostgreSQL, MySQL, SQLite, or SQL Server
- π§ Declarative: Define what you want, not how to build it
- π€ Automatic migration generation: Changes detected and converted to SQL migrations
- π Relationship management: Foreign keys and many-to-many relationships handled automatically
- β Built-in validation: Schema validation with helpful error messages
- π Change tracking: Automatic schema snapshots and diff generation
# Install from GitHub
go install github.com/ocomsoft/makemigrations@latest
# Or build from source
git clone https://github.com/ocomsoft/makemigrations
cd makemigrations
go build -o makemigrations .# Create project structure with YAML schema support
makemigrations init
# This creates:
# migrations/makemigrations.config.yaml # Configuration
# migrations/.schema_snapshot.yaml # State tracking (empty initially)
# schema/schema.yaml # Your schema definitionEdit schema/schema.yaml:
database:
name: myapp
version: 1.0.0
defaults:
postgresql:
blank: ''
now: CURRENT_TIMESTAMP
new_uuid: gen_random_uuid()
zero: "0"
true: "true"
false: "false"
tables:
- name: users
fields:
- name: id
type: uuid
primary_key: true
default: new_uuid
- name: email
type: varchar
length: 255
nullable: false
- name: created_at
type: timestamp
default: now
auto_create: true
- name: posts
fields:
- name: id
type: uuid
primary_key: true
default: new_uuid
- name: title
type: varchar
length: 200
nullable: false
- name: user_id
type: foreign_key
nullable: false
foreign_key:
table: users
on_delete: CASCADE# Generate migration from YAML schema
makemigrations makemigrations --name "initial_schema"
# Output:
# migrations/20240122134500_initial_schema.sql# PostgreSQL
export MAKEMIGRATIONS_DB_HOST=localhost
export MAKEMIGRATIONS_DB_PORT=5432
export MAKEMIGRATIONS_DB_USER=postgres
export MAKEMIGRATIONS_DB_PASSWORD=yourpassword
export MAKEMIGRATIONS_DB_NAME=yourdb
# MySQL, SQLite, SQL Server also supported# Apply all pending migrations
makemigrations goose up
# Check migration status
makemigrations goose statusWrite your schema once in YAML, deploy anywhere:
# Same YAML schema generates different SQL for each database
# PostgreSQL:
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
metadata JSONB DEFAULT '{}'
);
# MySQL:
CREATE TABLE users (
id CHAR(36) PRIMARY KEY DEFAULT (UUID()),
metadata JSON DEFAULT ('{}')
);
# SQLite:
CREATE TABLE users (
id TEXT PRIMARY KEY DEFAULT '',
metadata TEXT DEFAULT '{}'
);Define relationships declaratively:
# Foreign keys
- name: user_id
type: foreign_key
foreign_key:
table: users
on_delete: CASCADE
# Many-to-many relationships (use explicit junction tables)
# Define the junction table separately:
- name: post_categories # Junction table
fields:
- name: post_id
type: foreign_key
foreign_key:
table: posts
on_delete: CASCADE
- name: category_id
type: foreign_key
foreign_key:
table: categories
on_delete: CASCADEmakemigrations tracks your schema state and generates only the necessary changes:
# Add a new field to your YAML schema
- name: phone
type: varchar
length: 20
nullable: true
# Run makemigrations
makemigrations makemigrations
# Generates migration with only the new field:
# ALTER TABLE users ADD COLUMN phone VARCHAR(20);Destructive operations require review:
-- +goose Up
-- REVIEW: The following operation is destructive and requires manual review
-- +goose StatementBegin
DROP TABLE old_users;
-- +goose StatementEnd- Installation Guide - Complete setup instructions
- Schema Format Guide - Complete YAML schema reference
- Configuration Guide - Configuration options and environment variables
- makemigrations - Generate migrations from YAML schemas β Primary command
- init - Initialize new YAML-based projects
- goose - Apply migrations to database
- dump_sql - Preview generated SQL from schemas
- struct2schema - Generate YAML schemas from Go structs β New feature
- init_sql - Initialize SQL-based projects (alternative workflow)
- makemigrations_sql - Generate migrations from raw SQL
makemigrations supports 12 different database types with comprehensive provider implementations:
| Database | Status | Testing | Features |
|---|---|---|---|
| PostgreSQL | β Full support | β Fully tested | UUID, JSONB, arrays, advanced types |
| MySQL | β Supported | JSON, AUTO_INCREMENT, InnoDB features | |
| SQLite | β Supported | Simplified types, basic constraints | |
| SQL Server | β Supported | UNIQUEIDENTIFIER, NVARCHAR, BIT types | |
| Amazon Redshift | β Provider ready | SUPER JSON type, IDENTITY sequences, VARCHAR limits | |
| ClickHouse | β Provider ready | MergeTree engine, columnar storage, Nullable types | |
| TiDB | β Provider ready | MySQL-compatible, distributed, native BOOLEAN | |
| Vertica | β Provider ready | Columnar analytics, LONG VARCHAR, CASCADE support | |
| YDB (Yandex) | β Provider ready | Distributed SQL, Optional, native JSON | |
| Turso | β Provider ready | Edge SQLite, distributed capabilities | |
| StarRocks | β Provider ready | MPP analytics, OLAP engine, STRING types | |
| Aurora DSQL | β Provider ready | AWS serverless, PostgreSQL-compatible |
Note: Only PostgreSQL has been tested with real database instances. All other providers have comprehensive unit tests and follow database-specific SQL syntax, but may require additional testing and refinement for production use.
# Initialize YAML-based project
makemigrations init
# Generate migrations from YAML schemas
makemigrations makemigrations
# Preview changes without creating files
makemigrations makemigrations --dry-run
# Check if migrations are needed (CI/CD)
makemigrations makemigrations --check# Apply migrations
makemigrations goose up
# Check migration status
makemigrations goose status
# Rollback last migration
makemigrations goose down
# Create custom migration
makemigrations goose create add_indexes# Preview SQL without generating migrations
makemigrations dump_sql
# Generate YAML schemas from Go structs
makemigrations struct2schema --input ./models --output schema/schema.yaml
myproject/
βββ schema/
β βββ schema.yaml # Your YAML schema definition
βββ migrations/
β βββ makemigrations.config.yaml # Configuration
β βββ .schema_snapshot.yaml # State tracking
β βββ 20240122134500_initial.sql # Generated migrations
β βββ 20240123102000_add_posts.sql
βββ go.mod
βββ main.go
# Database connection
export MAKEMIGRATIONS_DB_HOST=localhost
export MAKEMIGRATIONS_DB_USER=postgres
export MAKEMIGRATIONS_DB_PASSWORD=password
export MAKEMIGRATIONS_DB_NAME=myapp
# Tool behavior (12 database types supported)
export MAKEMIGRATIONS_DATABASE_TYPE=postgresql # postgresql, mysql, sqlite, sqlserver, redshift, clickhouse, tidb, vertica, ydb, turso, starrocks, auroradsql
export MAKEMIGRATIONS_MIGRATION_SILENT=false
export MAKEMIGRATIONS_OUTPUT_VERBOSE=truemigrations/makemigrations.config.yaml:
database:
type: postgresql
quote_identifiers: true
migration:
directory: migrations
include_down_sql: true
review_comment_prefix: "-- REVIEW: "
output:
verbose: false
color_enabled: trueSee the Configuration Guide for complete options.
# Generate PostgreSQL migrations (fully tested)
makemigrations makemigrations --database postgresql
# Generate MySQL migrations for the same schema
makemigrations makemigrations --database mysql
# Generate migrations for cloud/analytics databases
makemigrations makemigrations --database redshift
makemigrations makemigrations --database clickhouse
makemigrations makemigrations --database tidb
# Same YAML schema, database-specific SQL output# Self-referencing foreign keys
- name: parent_id
type: foreign_key
nullable: true
foreign_key:
table: categories
on_delete: SET_NULL
# Many-to-many with explicit junction table
- name: post_tags # Junction table
fields:
- name: post_id
type: foreign_key
foreign_key:
table: posts
on_delete: CASCADE
- name: tag_id
type: foreign_key
foreign_key:
table: tags
on_delete: CASCADE
indexes:
- name: post_tags_unique
fields: [post_id, tag_id]
unique: truedefaults:
postgresql:
custom_uuid: custom_uuid_function()
app_timestamp: custom_timestamp()
tables:
- name: events
fields:
- name: id
type: uuid
default: custom_uuid # Uses your custom function# 1. Modify schema/schema.yaml
vim schema/schema.yaml
# 2. Preview changes
makemigrations makemigrations --dry-run
# 3. Generate migration
makemigrations makemigrations --name "add_user_preferences"
# 4. Review generated SQL
cat migrations/20240122134500_add_user_preferences.sql
# 5. Apply to database
makemigrations goose up# Developer A: Add new feature schema
git pull
vim schema/schema.yaml # Add new tables
makemigrations makemigrations --name "add_messaging_system"
git add . && git commit -m "Add messaging schema"
# Developer B: Pull and apply
git pull
makemigrations goose up # Apply new migrations# .github/workflows/migrations.yml
- name: Check for schema changes
run: |
makemigrations makemigrations --check
if [ $? -eq 1 ]; then
echo "Schema changes detected - migrations needed"
exit 1
fi
- name: Apply migrations
run: makemigrations goose up# Good: Organized, clear field definitions
tables:
- name: users
fields:
- name: id
type: uuid
primary_key: true
default: new_uuid
- name: email
type: varchar
length: 255
nullable: false# Good: Descriptive migration names
makemigrations makemigrations --name "add_user_authentication"
makemigrations makemigrations --name "optimize_product_queries"
# Avoid: Generic names
makemigrations makemigrations --name "changes"# Always test rollback capability
makemigrations goose up-by-one
makemigrations goose down
makemigrations goose up-by-oneWhile YAML schemas are the primary and recommended approach, makemigrations also supports:
For teams preferring direct SQL control:
# Initialize SQL-based project
makemigrations init_sql
# Generate migration from raw SQL
makemigrations makemigrations_sql --sql "CREATE TABLE test (id SERIAL);"Generate schemas from Go structs:
# Convert Go structs to YAML
makemigrations struct2schema --input ./models --output schema/schema.yaml
# Process specific files with custom configuration
makemigrations struct2schema --input models.go --config struct2schema.yaml --database postgresql- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Add tests for new functionality
- Ensure all tests pass:
go test ./... - Submit a pull request
MIT License - see LICENSE file for details.
- Documentation: Browse the
/docsdirectory - Issues: Report bugs on GitHub Issues
- Discussions: Join GitHub Discussions
Ready to get started? Check out the Installation Guide and Schema Format Guide!