PocketBase provides a simple migrate command, allowing you to share your DB structure, create collections programmatically, initialize default settings and/or run anything that needs to be executed only once.

The migrate command comes also with "automigrate" functionality that will create seamlessly the necessary migration files for you when making collection changes from the Admin UI.

You can write migrations with Go or JavaScript (more information will be available soon).

    Enable Go migrations

    The prebuilt executable enables the migrate command by default, but when you are extending PocketBase with Go you have to enable it manually:

    // main.go package main import ( "log" "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/plugins/migratecmd" // uncomment once you have at least one .go migration file in the "migrations" directory // _ "yourpackage/migrations" ) func main() { app := pocketbase.New() migratecmd.MustRegister(app, app.RootCmd, &migratecmd.Options{ Automigrate: true, // auto creates migration files when making collection changes }) if err := app.Start(); err != nil { log.Fatal(err) } }

    migrate create

    The easiest way to create a new migration file is to use migrate create during development:

    // Since the "create" command makes sense only during development, // it is expected the user to be in the app working directory // and to be using "go run ..." [root@dev project]$ go run main.go migrate create "your_new_migration"

    The above will create a new directory migrations with a blank migration file inside it.

    To make your application aware of the registered migrations, you simply have to import the above migrations package in one of your main package files:

    package main import _ "yourpackage/migrations" // ...

    Here is for example what a single migration file could look like:

    // migrations/1655834400_your_new_migration.go package migrations import ( "github.com/pocketbase/dbx" "github.com/pocketbase/pocketbase/daos" m "github.com/pocketbase/pocketbase/migrations" ) func init() { m.Register(func(db dbx.Builder) error { // set a default "pending" status to all articles query := db.NewQuery("UPDATE articles SET status = 'pending' WHERE status = ''") if _, err := query.Execute(); err != nil { return err } // you can also access the Dao helpers dao := daos.New(db) record, _ := dao.FindRecordById("articles", "RECORD_ID") record.Set("status", "active") if err := dao.SaveRecord(record); err != nil { return err } // and even set default app settings settings, _ := dao.FindSettings() settings.Meta.AppName = "test" settings.Smtp.Enabled = false if err := dao.SaveSettings(settings); err != nil { return err } return nil }, func(db dbx.Builder) error { // revert changes... return nil }) }
    Because the migrations are Go functions, besides applying schema changes, they could be used also to adjust existing data to fit the new schema or any other app specific logic that you want to run only once.
    And as a bonus, being .go files also ensures that the migrations will be embedded seamlessly in your final executable.

    When you deploy the final executable on your production server, the new migrations will be auto applied with the start of the application.

    Optionally, you could apply new migrations explicitly using migrate up:

    [root@dev ~]$ ./yourapp migrate up

    To revert the last applied migration(s), you could run migrate down [number]:

    [root@dev ~]$ ./yourapp migrate down

    migrate collections

    PocketBase comes also with a migrate collections command that will generate a full snapshot of your current Collections configuration without having to type it manually:

    // Since the "collections" command makes sense only during development, // it is expected the user to be in the app working directory // and to be using "go run ..." [root@dev project]$ go run main.go migrate collections

    Similar to the migrate create command, this will generate a new migration file in the migrations directory.

    It is safe to run the command multiple times and generate multiple migration files.

    If Automigrate is enabled, running this command usually is not necessarily since every collection change will have its own migration file.