Configuration
Configure go-migration using YAML, JSON, or environment variables — complete reference with all supported fields and default values.
Configuration
go-migration supports configuration through YAML files, JSON files, and environment variables. When using migrator.Run(), the config file defaults to migration.json in the current directory. You can also specify a path with the --config flag.
# Uses migration.json in the current directory (default)
go-migration migrate
# Specify a custom config file
go-migration migrate --config=./config/production.json
go-migration migrate --config=./config/go-migration.yamlPerubahan nama file konfigurasi: Nama file konfigurasi default telah berubah beberapa kali: migration.yaml / database.yaml → go-migration.yaml (v1.0.0) → migration.json (v1.0.0). Sejak v1.0.0, migration.json adalah default. File YAML (go-migration.yaml, migration.yaml, database.yaml) masih didukung melalui flag --config, tetapi saat file YAML dimuat, go-migration menampilkan peringatan deprecation di console.
Configuration File
The configuration file defines your database connection, pool settings, migration table name, and logging preferences.
Create a migration.json file in your project root:
{
"driver": "postgres",
"host": "localhost",
"port": 5432,
"database": "myapp",
"username": "dbuser",
"password": "dbpass",
"sslmode": "disable",
"max_open_conns": 25,
"max_idle_conns": 5,
"conn_max_lifetime": 300,
"migration_table": "migrations",
"log_level": "info"
}Create a go-migration.yaml file in your project root:
# Database driver: postgres, mysql, or sqlite
driver: postgres
# Connection details
host: localhost
port: 5432
database: myapp
username: dbuser
password: dbpass
# SSL mode (PostgreSQL only)
sslmode: disable
# Connection pool settings
max_open_conns: 25
max_idle_conns: 5
conn_max_lifetime: 300 # seconds
# Migration settings
migration_table: migrations
# Logging
log_level: infoSupported Fields
| Field | Type | Required | Description |
|---|---|---|---|
default | string | No | Name of the default connection to use (see Multi-Connection Configuration) |
connections | map | No | Map of named database connections (see Multi-Connection Configuration) |
driver | string | Yes | Database driver — postgres, mysql, or sqlite |
host | string | Yes | Database server hostname or IP address |
port | int | Yes | Database server port |
database | string | Yes | Database name (or file path for SQLite) |
username | string | Yes | Database user |
password | string | Yes | Database password |
sslmode | string | No | SSL mode for PostgreSQL (disable, require, verify-ca, verify-full) |
max_open_conns | int | No | Maximum number of open connections |
max_idle_conns | int | No | Maximum number of idle connections in the pool |
conn_max_lifetime | int | No | Maximum connection lifetime in seconds |
migration_table | string | No | Name of the migrations tracking table |
migration_dir | string | No | Directory for migration files (default: database/migrations) |
seeder_dir | string | No | Directory for seeder files (default: database/seeders) |
factory_dir | string | No | Directory for factory files (default: database/factories) |
log_level | string | No | Logging verbosity — debug, info, warn, error |
Environment Variable Fallback
go-migration checks for environment variables when a field is not set in the configuration file. This lets you keep secrets out of config files and override settings per environment.
Naming Convention
Environment variables use uppercase names with a DB_ prefix for connection fields:
| Config Field | Environment Variable |
|---|---|
host | DB_HOST |
port | DB_PORT |
database | DB_NAME |
username | DB_USER |
password | DB_PASSWORD |
driver | DB_DRIVER |
sslmode | DB_SSLMODE |
Directory Settings
go-migration also supports environment variables for directory configuration with the GOMIGRATE_ prefix:
| Config Field | Environment Variable | Default |
|---|---|---|
migration_dir | GOMIGRATE_MIGRATION_DIR | database/migrations |
seeder_dir | GOMIGRATE_SEEDER_DIR | database/seeders |
factory_dir | GOMIGRATE_FACTORY_DIR | database/factories |
migration_table | GOMIGRATE_MIGRATION_TABLE | migrations |
log_level | GOMIGRATE_LOG_LEVEL | info |
log_output | GOMIGRATE_LOG_OUTPUT | console |
Resolution Order
For each field, go-migration resolves the value in this order:
- Configuration file — value from YAML or JSON
- Environment variable — fallback if the config field is empty or missing
- Default value — built-in default if neither is set (for optional fields)
# Set environment variables for production
export DB_HOST=prod-db.example.com
export DB_PORT=5432
export DB_NAME=myapp_production
export DB_USER=app_user
export DB_PASSWORD=s3cretEnvironment variables only apply as fallbacks. If a value is explicitly set in the configuration file, the environment variable is ignored for that field.
Minimal Config with Environment Variables
You can use a minimal configuration file and let environment variables handle the sensitive values:
{
"driver": "postgres",
"sslmode": "require",
"migration_table": "schema_migrations",
"log_level": "info"
}driver: postgres
sslmode: require
migration_table: schema_migrations
log_level: info
# host, port, database, username, password
# resolved from DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORDAvoid committing passwords and secrets to version control. Use environment variables or a .env file (excluded from git) for sensitive values.
Default Values
Optional settings use these defaults when not specified in the config file or environment:
| Setting | Default Value | Description |
|---|---|---|
migration_table | migrations | Name of the table that tracks applied migrations |
migration_dir | database/migrations | Directory for migration files |
seeder_dir | database/seeders | Directory for seeder files |
factory_dir | database/factories | Directory for factory files |
max_open_conns | 0 (unlimited) | Maximum open database connections |
max_idle_conns | 2 | Maximum idle connections in the pool |
conn_max_lifetime | 0 (no limit) | Maximum connection lifetime in seconds |
log_level | info | Logging verbosity level |
sslmode | disable | SSL mode for PostgreSQL connections |
Pool settings map directly to Go's *sql.DB methods. See Pool Configuration for tuning recommendations based on your workload.
Driver-Specific Examples
driver: postgres
host: localhost
port: 5432
database: myapp
username: postgres
password: secret
sslmode: disable
max_open_conns: 25
max_idle_conns: 5
conn_max_lifetime: 300
migration_table: migrations
log_level: infodriver: mysql
host: localhost
port: 3306
database: myapp
username: root
password: secret
max_open_conns: 25
max_idle_conns: 5
conn_max_lifetime: 300
migration_table: migrations
log_level: infodriver: sqlite
database: ./data/myapp.db
migration_table: migrations
log_level: infoSQLite uses the database field as the file path. The host, port, username, and password fields are not required.
Multi-Connection Configuration
New in v1.0.0 — the configuration file now supports a default field and a connections map for managing multiple database connections.
The default field specifies which connection is used when no specific connection is requested. The connections field is a map of named database connections, where each key is a connection name and the value contains the connection settings.
Directory and table settings (migration_dir, seeder_dir, factory_dir, migration_table, log_level) are defined at the top level and apply globally across all connections.
{
"default": "postgres",
"connections": {
"postgres": {
"driver": "postgres",
"host": "${DB_HOST}",
"port": 5432,
"database": "${DB_DATABASE}",
"username": "${DB_USERNAME}",
"password": "${DB_PASSWORD}",
"sslmode": "disable"
},
"mysql": {
"driver": "mysql",
"host": "${MYSQL_HOST}",
"port": 3306,
"database": "${MYSQL_DATABASE}",
"username": "${MYSQL_USERNAME}",
"password": "${MYSQL_PASSWORD}"
}
},
"migration_dir": "database/migrations",
"seeder_dir": "database/seeders",
"factory_dir": "database/factories",
"migration_table": "migrations",
"log_level": "info"
}# Default connection name
default: postgres
# Multiple database connections
connections:
postgres:
driver: postgres
host: ${DB_HOST}
port: 5432
database: ${DB_DATABASE}
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
sslmode: disable
mysql:
driver: mysql
host: ${MYSQL_HOST}
port: 3306
database: ${MYSQL_DATABASE}
username: ${MYSQL_USERNAME}
password: ${MYSQL_PASSWORD}
# Directory and settings (apply globally)
migration_dir: database/migrations
seeder_dir: database/seeders
factory_dir: database/factories
migration_table: migrations
log_level: infoWhen using the --config flag, the multi-connection structure works the same way:
go-migration migrate --config=./config/migration.jsonThe flat configuration format (without default and connections) is still supported. If connections is not present, go-migration treats the top-level fields as a single connection — no changes needed for existing config files.
Environment Variable Interpolation
You can embed environment variable references directly in your YAML or JSON config values using ${VAR_NAME} placeholders. This is different from the environment variable fallback — interpolation lets you compose values from multiple environment variables.
driver: postgres
host: ${DB_HOST}
port: 5432
database: ${DB_NAME}
username: ${DB_USER}
password: ${DB_PASSWORD}
sslmode: ${DB_SSLMODE}
log_level: infoHow It Works
Interpolation happens after reading the file and before YAML/JSON parsing:
- go-migration reads the raw config file content
- All
${VAR_NAME}placeholders are replaced with the corresponding environment variable values - The resulting string is then parsed as YAML or JSON
Auto-Unquote for JSON (v1.0.0)
When using JSON config files, InterpolateEnv automatically removes surrounding quotes for values that resolve to numeric, boolean (true/false), or null types. This means your JSON stays valid with correct types after interpolation.
{
"driver": "postgres",
"host": "${DB_HOST}",
"port": "${DB_PORT}",
"database": "${DB_NAME}",
"sslmode": "disable"
}With DB_HOST=localhost, DB_PORT=5432, and DB_NAME=myapp, the result after interpolation is:
{
"driver": "postgres",
"host": "localhost",
"port": 5432,
"database": "myapp",
"sslmode": "disable"
}Notice that "port": "${DB_PORT}" becomes "port": 5432 (a number, not the string "5432"). The same applies to boolean and null values:
| Environment Variable | JSON Before | JSON After |
|---|---|---|
DB_PORT=5432 | "port": "${DB_PORT}" | "port": 5432 |
ENABLE_SSL=true | "ssl": "${ENABLE_SSL}" | "ssl": true |
EXTRA=null | "extra": "${EXTRA}" | "extra": null |
DB_HOST=localhost | "host": "${DB_HOST}" | "host": "localhost" |
Auto-unquote hanya berlaku untuk file JSON. Pada file YAML, tipe data sudah ditangani secara native oleh parser YAML sehingga tidak perlu unquote.
Escaping
To produce a literal ${VAR_NAME} in your config (without interpolation), use the double-dollar escape sequence:
# This resolves to the value of DB_HOST
host: ${DB_HOST}
# This produces the literal string "${NOT_REPLACED}"
some_field: $${NOT_REPLACED}Missing Variables
If any ${VAR_NAME} references an environment variable that is not set, go-migration returns an error listing all unresolved variables. This prevents silent misconfiguration.
All unresolved ${VAR_NAME} placeholders are reported in a single error message, so you can fix them all at once rather than one at a time.
Config Validation
go-migration validates your configuration at load time and reports all violations in a single error. This catches common mistakes before any database operations are attempted.
Validated Fields
| Field | Rule |
|---|---|
driver | Must be postgres, mysql, or sqlite |
port | Must be a positive number when specified |
log_level | Must be debug, info, warn, or error |
log_output | Must be console, file, or both |
max_open_conns | Must be non-negative |
max_idle_conns | Must be non-negative |
Example Error
If multiple fields are invalid, you get a single error with all violations:
config validation failed:
- driver must be one of: postgres, mysql, sqlite (got "mongo")
- port must be positive (got -1)
- log_level must be one of: debug, info, warn, error (got "verbose")Validation runs after environment variable interpolation and fallback resolution, so the final resolved values are what gets validated.
Programmatic Usage
The config package is publicly available at config/, so you can import it directly in your own Go projects — no need to reimplement config loading, validation, or environment variable interpolation.
package main
import (
"fmt"
"log"
"github.com/gopackx/go-migration/config"
)
func main() {
// Load configuration from a YAML or JSON file
cfg, err := config.Load("migration.json")
if err != nil {
log.Fatalf("failed to load config: %v", err)
}
// Apply default values for optional fields
cfg.ApplyDefaults()
// Validate the resolved configuration
if err := cfg.Validate(); err != nil {
log.Fatalf("invalid config: %v", err)
}
fmt.Printf("Connected to %s on %s:%d\n", cfg.Database, cfg.Host, cfg.Port)
}config.Load() handles file reading, YAML/JSON parsing, and environment variable interpolation (${VAR_NAME}) in a single call. Follow it with ApplyDefaults() and Validate() for a fully resolved and validated configuration.
What's Next?
- Framework Integration — use go-migration with Gin, Echo, Fiber, or net/http
- CLI Reference — run migrations from the command line
- Error Handling — diagnose and handle migration errors