Skip to content

Goose provider

The Provider type is the entry point for the goose library. It initializes the state and provides methods to run migrations. It does not have global state, so you can create multiple providers with different configurations.

Initialize a provider by calling goose.NewProvider():

func NewProvider(
    dialect Dialect,
    db *sql.DB,
    fsys fs.FS,
    opts ...ProviderOption,
) (*Provider, error){
    // ...
}

Provider

Dialect

The Dialect defines the SQL dialect of the database. Simply put, goose needs to know the raw SQL syntax of the database its working with.

Each dialect has a corresponding constant backed by a database.Store implementation.

For most users its sufficient to use one of the natively supported dialects and not worry about the database store. For more advanced users, you may bring your own dialect and store, see the TODO section for more information.

db

The *sql.DB is the database connection that goose will use to run migrations. Goose intentionally does not care which database driver is used.

The caller is responsible for matching the dialect with the database driver. For example, if you are using the goose.DialectPostgres dialect, you'd pick the jackc/pgx driver.

fsys

The fs.FS is the filesystem abstraction that goose will use to read migration files. This is will typically be os.DirFS, embed.FS.

Quite often you may have a heirarchy of directories with migrations, in which case you can use fs.Sub to create a sub filesystem.

fsys, err := fs.Sub(embeddedFS, "migrations")

And then pass the fsys to the provider.

Provider Options

The ProviderOption is a functional option type that allows you to configure and customize the provider.

WithStore

WithVerbose

func WithVerbose(b bool)

This option enables verbose logging of the migration process. For example, here's the output of running an up migration with verbose logging:

goose: OK    up 00001_users_table.sql (1.32ms)
goose: OK    up 00002_add_users.go (638.96µs)
goose: OK    up 00003_count_users.go (561.58µs)
goose: successfully migrated database, current version: 3

By default, the provider methods do not log anything by default.

WithSessionLocker

func WithSessionLocker(locker lock.SessionLocker)

By default, goose does not lock the database during migrations. It is up to the caller to ensure migrations are run in a safe manner. Which means in certain environments, such as Kubernetes, you may have multiple instances of your application running migrations concurrently.

By configuring a SessionLocker, you can ensure that only one instance of your application runs migrations at a time.

The lock package provides a few implementations of the SessionLocker interface:

Postgres

The NewPostgresSessionLocker function creates a SessionLocker that can be used to acquire and release a lock for synchronization purposes. The lock acquisition is retried until it is successfully acquired or until the failure threshold is reached.

The default lock duration is set to 5 minutes, and the default unlock duration is set to 1 minute. These can be tuned.

WithExcludeNames

func WithExcludeNames(excludes []string)

The option excludes the given file names from the list of migrations. If called multiple times, the list of excludes is merged.

WithExcludeVersions

func WithExcludeVersions(versions []int64)

This option excludes the given versions from the list of migrations. If called multiple times, the list of excludes is merged.

WithGoMigrations

func WithGoMigrations(migrations ...*Migration)

This option adds the given Go migration to the list of migrations. The migration must be constructed using the NewGoMigration constructor.

NewGoMigration

func NewGoMigration(version int64, up, down *GoFunc) *Migration

This function creates a new Go migration, which may be registered with a provider or globally.

Both up and down functions may be nil, in which case the migration will be recorded in the versions table but no functions will be run. This is useful for recording (up) or deleting (down) a version without running any functions.

A Go migration can either be executed within or outside a transaction and only one can be set. If both are set, an error will be returned.

RunTx func(ctx context.Context, tx *sql.Tx) error

// or

RunDB func(ctx context.Context, db *sql.DB) error

WithDisableGlobalRegistry

func WithDisableGlobalRegistry(b bool)

This option disables the global registry. By default, goose uses a global registry to store all migrations. This is useful for running migrations in a single process. If you are running migrations in multiple processes, you should disable the global registry and register migrations with the provider.

WithAllowOutofOrder

func WithAllowOutofOrder(b bool)

This option allows migrations to be run out-of-order, this is often called "allow missing" migrations. By default, goose will error if it detects that a migration is missing.

For example: migrations 1,3 are applied to the database and then versions 2,6 are introduced. If this option is true, then goose will apply 2 (missing) and 6 (new) instead of raising an error.

The final order of applied migrations will be: 1,3,2,6. Out-of-order migrations are always applied first, followed by new migrations.

WithDisableVersioning

func WithDisableVersioning(b bool)

This option disables versioning. Disabling versioning allows applying migrations without tracking the versions in the database schema table. Useful for tests, seeding a database or running ad-hoc queries. By default, goose will track all versions in the database schema table.