Skip to main content

PostgreSQL Driver

PostgreSQL is Queen's reference production driver.

Packages

import (
"database/sql"

"github.com/yaop-labs/queen"
"github.com/yaop-labs/queen/drivers/postgres"
_ "github.com/jackc/pgx/v5/stdlib"
)

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

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

With native pgxpool.Pool:

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

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

Queen.Close() closes the database/sql adapter handle, not the caller-owned pool.

How it works

AreaImplementation
Migration tableCREATE TABLE IF NOT EXISTS <table> with metadata columns.
Identifier quotingDouble quotes.
Placeholders$1, $2, ...
Lockingpg_advisory_lock(lockID) on a pinned *sql.Conn.
Unlockpg_advisory_unlock(lockID) on the same pinned connection.
Lock keyStable FNV-1a hash of the migration table name.
Executiondatabase/sql transaction through the shared base driver.
Atomic recordYes. Implements queen.TransactionalRecorder via RecordTx and RemoveTx.
Pool supportpostgres.NewFromPool and NewFromPoolWithTableName.

Guarantees

  • One Queen operation on one driver instance cannot overwrite the advisory lock connection.
  • PostgreSQL migration body and migration metadata are committed in the same transaction.
  • LockTimeout bounds advisory lock acquisition.
  • ErrLockTimeout wraps lock timeout failures.

Limitations

  • Advisory lock IDs are derived from table names. Use distinct table names for distinct migration domains.
  • PostgreSQL is the most tested production path; behavior documented here is stronger than other drivers.
  • DDL still follows PostgreSQL's own transaction rules.
production:
driver: postgres
dsn: "${DATABASE_URL}"
table: queen_migrations
lock_timeout: 30m
require_confirmation: true
require_explicit_unlock: true