--- id: versioned-migrations title: Versioned Migrations --- If you are using the Atlas migration engine you are able to use the versioned migrations feature of it. Instead of applying the computed changes directly to the database, it will generate a set of migration files containing the necessary SQL statements to migrate the database. These files can then be edited to your needs and be applied by any tool you like (like golang-migrate, Flyway, liquibase). ![atlas-versioned-migration-process](https://entgo.io/images/assets/migrate-atlas-versioned.png) ## Configuration In order to have Ent make the necessary changes to your code, you have to enable this feature with one of the two options: 1. If you are using the default go generate configuration, simply add the `--feature sql/versioned-migration` to the `ent/generate.go` file as follows: ```go package ent //go:generate go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/versioned-migration ./schema ``` 2. If you are using the code generation package (e.g. if you are using an Ent extension), add the feature flag as follows: ```go //go:build ignore package main import ( "log" "entgo.io/ent/entc" "entgo.io/ent/entc/gen" ) func main() { err := entc.Generate("./schema", &gen.Config{}, entc.FeatureNames("sql/versioned-migration")) if err != nil { log.Fatalf("running ent codegen: %v", err) } } ``` ## Generating Versioned Migration Files ### From Client After regenerating the project, there will be an extra `Diff` method on the Ent client that you can use to inspect the connected database, compare it with the schema definitions and create sql statements needed to migrate the database to the graph. ```go package main import ( "context" "log" "/ent" "ariga.io/atlas/sql/migrate" "entgo.io/ent/dialect/sql/schema" ) func main() { client, err := ent.Open("mysql", "root:pass@tcp(localhost:3306)/test") if err != nil { log.Fatalf("failed connecting to mysql: %v", err) } defer client.Close() ctx := context.Background() // Create a local migration directory. dir, err := migrate.NewLocalDir("migrations") if err != nil { log.Fatalf("failed creating atlas migration directory: %v", err) } // Write migration diff. err = client.Schema.Diff(ctx, schema.WithDir(dir)) if err != nil { log.Fatalf("failed creating schema resources: %v", err) } } ``` You can then create a new set of migration files by simply calling `go run -mod=mod main.go`. ### From Graph You can also generate new migration files without an instantiated Ent client. This can be useful if you want to make the migration file creation part of a go generate workflow. ```go package main import ( "context" "log" "ariga.io/atlas/sql/migrate" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/schema" "entgo.io/ent/entc" "entgo.io/ent/entc/gen" ) func main() { // Load the graph. graph, err := entc.LoadGraph("/.schema", &gen.Config{}) if err != nil { log.Fatalln(err) } tbls, err := graph.Tables() if err != nil { log.Fatalln(err) } // Create a local migration directory. d, err := migrate.NewLocalDir("migrations") if err != nil { log.Fatalln(err) } // Open connection to the database. dlct, err := sql.Open("mysql", "root:pass@tcp(localhost:3306)/test") if err != nil { log.Fatalln(err) } // Inspect it and compare it with the graph. m, err := schema.NewMigrate(dlct, schema.WithDir(d)) if err != nil { log.Fatalln(err) } if err := m.Diff(context.Background(), tbls...); err != nil { log.Fatalln(err) } } ``` ## Apply Migrations The Atlas migration engine does not support applying the migration files onto a database yet, therefore to manage and execute the generated migration files, you have to rely on an external tool (or execute them by hand). By default, Atlas generates one "up" and one "down" migration file for the computed diff. These files are compatible with the popular [golang-migrate/migrate](https://github.com/golang-migrate/migrate) package, and you can use that tool to manage the migrations in you deployments. ```shell migrate -source file://migrations -database mysql://root:pass@tcp(localhost:3306)/test up ``` ## Moving from Auto-Migration to Versioned Migrations In case you already have an Ent application in production and want to switch over from auto migration to the new versioned migration, you need to take some extra steps. 1. Create an initial migration file (or several files if you want) reflecting the currently deployed state. To do this make sure your schema definition is in sync with your deployed version. Then spin up an empty database and run the diff command once as described above. This will create the statements needed to create the current state of your schema graph. 2. Configure the tool you use to manage migrations to consider this file as **applied**. In case of `golang-migrate` this can be done by forcing your database version as described [here](https://github.com/golang-migrate/migrate/blob/master/GETTING_STARTED.md#forcing-your-database-version).