Skip to main content

Use Queen as a Library

Use the library API when migrations should run from your application startup, tests, or an internal deploy tool.

Create a Queen instance

db, err := sql.Open("pgx", os.Getenv("DATABASE_URL"))
if err != nil {
return err
}
defer db.Close()

q := queen.New(postgres.New(db))
defer q.Close()

queen.New accepts options:

q := queen.New(
postgres.New(db),
queen.WithLogger(logger),
queen.WithTap(tap.NewJSONSink(os.Stdout)),
)

Configure behavior

q := queen.NewWithConfig(postgres.New(db), &queen.Config{
TableName: "queen_migrations",
LockTimeout: 10 * time.Minute,
SkipLock: false,
})

Use SkipLock: true only for controlled single-runner cases. For production PostgreSQL, keep locking enabled.

Config fields:

FieldDefaultPurpose
TableNamequeen_migrationsMigration metadata table.
LockTimeout30mDriver lock acquisition timeout.
SkipLockfalseSkip driver lock acquisition.
NamingnilOptional version naming policy.
IsolationLevelsql.LevelDefaultDefault transaction isolation level.

Register migrations

func Register(q *queen.Queen) {
q.MustAdd(queen.M{
Version: "001",
Name: "create_users",
UpSQL: `CREATE TABLE users (id SERIAL PRIMARY KEY, email TEXT NOT NULL);`,
DownSQL: `DROP TABLE users;`,
})
}

MustAdd is convenient during program startup. Use Add if you want to return registration errors instead of panicking.

Apply and rollback

err := q.Up(ctx) // apply all pending migrations
err = q.UpSteps(ctx, 2) // apply up to 2 pending migrations
err = q.Down(ctx, 1) // rollback one migration
err = q.Reset(ctx) // rollback all applied migrations

Down(ctx, n <= 0) rolls back exactly one latest migration. Use Reset(ctx) for "everything".

Inspect before running

plans, err := q.DryRun(ctx, queen.DirectionUp, 0)
if err != nil {
return err
}

for _, p := range plans {
fmt.Printf("%s %s destructive=%v\n", p.Version, p.Name, p.IsDestructive)
}

Validate(ctx) checks registration validity and applied checksum drift before you run migrations.

Runtime API

MethodPurpose
Add(m queen.M) errorRegister one migration.
MustAdd(m queen.M)Register one migration and panic on invalid input.
Up(ctx)Apply all pending migrations.
UpSteps(ctx, n)Apply up to n pending migrations; n <= 0 means all.
Down(ctx, n)Roll back n latest migrations; n <= 0 means one.
Reset(ctx)Roll back all applied migrations.
Status(ctx)Return status for all registered migrations.
Validate(ctx)Validate registration and checksum drift.
DryRun(ctx, direction, limit)Return migration plans without executing.
Explain(ctx, version)Return detailed plan for one migration.
FindMigration(version)Return a defensive copy of one registered migration.
Driver()Return the underlying driver.
SQLDB()Return the underlying *sql.DB when the driver exposes it.
Close()Close driver resources.

Long-running public operations on a single Queen instance are serialized internally. For production deploys, still run one intentional migrator job per environment.

Status values

Status(ctx) reports:

StatusMeaning
pendingRegistered in code, not recorded in the database.
appliedRegistered and recorded with matching checksum.
modifiedApplied, but the registered SQL checksum differs from the stored checksum.

modified blocks migration execution until you resolve the drift.

pgxpool adapter

If your app already owns a pgxpool.Pool, use the adapter:

pool, err := pgxpool.New(ctx, os.Getenv("DATABASE_URL"))
if err != nil {
return err
}
defer pool.Close()

q := queen.New(postgres.NewFromPool(pool))
defer q.Close()

Closing Queen closes the database/sql adapter handle, not the caller-owned pool.

Testing helper

Queen includes a small test helper:

func TestMigrations(t *testing.T) {
driver := setupTestDriver(t)
q := queen.NewTest(t, driver)

migrations.Register(q.Queen)
q.TestUpDown()
}

Useful helper methods include MustUp, MustDown, MustReset, MustValidate, TestUpDown, and TestRollback.