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
| Area | Implementation |
|---|---|
| Migration table | CREATE TABLE IF NOT EXISTS <table> with metadata columns. |
| Identifier quoting | Double quotes. |
| Placeholders | $1, $2, ... |
| Locking | pg_advisory_lock(lockID) on a pinned *sql.Conn. |
| Unlock | pg_advisory_unlock(lockID) on the same pinned connection. |
| Lock key | Stable FNV-1a hash of the migration table name. |
| Execution | database/sql transaction through the shared base driver. |
| Atomic record | Yes. Implements queen.TransactionalRecorder via RecordTx and RemoveTx. |
| Pool support | postgres.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.
LockTimeoutbounds advisory lock acquisition.ErrLockTimeoutwraps 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.
Recommended production config
production:
driver: postgres
dsn: "${DATABASE_URL}"
table: queen_migrations
lock_timeout: 30m
require_confirmation: true
require_explicit_unlock: true