This feature lets a single migrations directory contain files that are applied only against a specific deployment target — for example normal MongoDB, AWS DocumentDB, or a sharded DocumentDB cluster where some operations are restricted.
<version>_<identifier>[.<profile>].(up|down).<ext>
<version>— the usual numeric ordering (001,20240101120000, …).<identifier>— descriptive name, e.g.create_user.<profile>— optional deployment profile, e.g.mongo,documentdb,documentdb-sharded. Letters, digits,-, and_are allowed.<ext>— file extension, e.g.sql,json.
Examples in one directory:
001_create_user.up.json # default (untagged)
001_create_user.down.json
001_create_user.mongo.up.json # mongo-only variant
001_create_user.mongo.down.json
001_create_user.documentdb-sharded.up.json # documentdb-sharded only variant
001_create_user.documentdb-sharded.down.json
002_enable_change_streams.mongo.up.json # mongo-only variant
002_enable_change_streams.mongo.down.json
The runtime selects files based on the active profile. Profile names
are arbitrary strings — mongo, documentdb, and documentdb-sharded
below are illustrative, not reserved.
| Active profile | Which files are loaded |
|---|---|
| (empty / unset) | only files without a profile tag |
any name X |
files tagged .X. and untagged files |
Override rule:
When the active profile is X and both an untagged file and a .X.
file exist for the same (version, direction), the .X. file wins. The
untagged file acts as the default; the tagged file is the per-profile
override.
Other notes:
- A file tagged with a profile different from the active one is never loaded.
- Duplicate detection key is
(version, direction, profile)— not the identifier. So001_foo.up.sql+001_bar.up.sqlis a duplicate (same untagged slot),001_foo.mongo.up.sql+001_bar.mongo.up.sqlis a duplicate (samemongoslot), but001_foo.up.sql+001_foo.mongo.up.sqlis not a duplicate (different profiles — the tagged file is the override). Violations surface assource.ErrDuplicateMigrationat source-driver init time. - The numeric
<version>is what gets written to the database'sschema_migrationsrecord, regardless of which profile-variant ran. The parsedMigration.Identifieris suffixed with[profile]so log lines make the chosen variant obvious.
migrate -source file://./migrations \
-database "mongodb://localhost:27017/mydb" \
-profile mongo \
up
-profile falls back to $MIGRATE_PROFILE:
export MIGRATE_PROFILE=documentdb-sharded
migrate -source file://./migrations \
-database "mongodb://shared-docdb.cluster.local:27017/mydb" \
up
The CLI flag takes precedence over the env var.
import (
"github.com/AccelByte/migrate/v4"
_ "github.com/AccelByte/migrate/v4/database/mongodb"
_ "github.com/AccelByte/migrate/v4/source/file"
)
m, err := migrate.New("file://./migrations", "mongodb://localhost:27017/mydb")
if err != nil { panic(err) }
defer m.Close()
// returns false if the source driver does not implement source.ProfileAware
if !m.SetSourceProfile("documentdb") {
panic("source driver does not support profiles")
}
if err := m.Up(); err != nil && err != migrate.ErrNoChange {
panic(err)
}When using a hand-built source driver via iofs.New:
import (
"embed"
"github.com/AccelByte/migrate/v4"
"github.com/AccelByte/migrate/v4/source/iofs"
)
//go:embed migrations/*
var fsys embed.FS
src, err := iofs.New(fsys, "migrations")
if err != nil { panic(err) }
// Set the profile before passing to migrate.NewWithSourceInstance.
src.(source.ProfileAware).SetProfile("mongo")
m, err := migrate.NewWithSourceInstance("iofs", src, dbURL)-
Pick one profile per database and stick with it. Switching profiles on the same database can produce inconsistent state because both variants share the same version number.
-
Source-driver support matrix:
Source driver Profile-aware? file✅ iofs✅ httpfs,godoc_vfs,pkger❌ (share httpfs.PartialDriver— could be added later)aws_s3,bitbucket,github,github_ee,gitlab,go_bindata,google_cloud_storage,stub❌ If
-profileis set against an unsupported driver, the CLI logs a warning and loads all files — including profile-tagged ones, which is almost certainly not what you want. Pin one of the supported drivers if you rely on profiles.
Directory:
migrations/
001_users.up.json
001_users.down.json
001_users.documentdb-sharded.up.json
001_users.documentdb-sharded.down.json
002_indexes.mongo.up.json
002_indexes.mongo.down.json
002_indexes.documentdb.up.json
002_indexes.documentdb.down.json
Runs:
# Plain mongo deployment:
# v1: 001_users.up.json (untagged — no mongo override exists)
# v2: 002_indexes.mongo.up.json (mongo variant)
MIGRATE_PROFILE=mongo migrate -path migrations -database "$URL" up
# AWS DocumentDB deployment:
# v1: 001_users.up.json (untagged — no documentdb override)
# v2: 002_indexes.documentdb.up.json (documentdb variant)
MIGRATE_PROFILE=documentdb migrate -path migrations -database "$URL" up
# Shared DocumentDB deployment:
# v1: 001_users.documentdb-sharded.up.json (override wins over untagged)
# v2: skipped — neither an untagged nor a documentdb-sharded variant exists
MIGRATE_PROFILE=documentdb-sharded migrate -path migrations -database "$URL" up
# No profile — applies only the untagged files: v1 only.
migrate -path migrations -database "$URL" up