# modules/postgres

```go
import "apistock.dev/modules/postgres"
```

Package postgres connects apistock apps to PostgreSQL: a pgx connection pool with OpenTelemetry tracing, transactions, error classification for repositories, a readiness check and goose migrations (ADR-0005, ADR-0032).

Repositories hold a [DBTX](#DBTX), so the same store runs on the pool or inside a transaction started with [InTx](#InTx). Transactions are passed explicitly, never stored in a context (ADR-0030).

This package is the pgx adapter, so pgx types appear in its API and its errors wrap pgx errors. Repositories translate them into domain errors with [IsNoRows](#IsNoRows), [UniqueViolation](#UniqueViolation) and the other helpers before returning.

Stability: pre-1.0 (ADR-0015).

## Constants

### const DefaultConnectTimeout

```go
const DefaultConnectTimeout = 5 * time.Second
```

DefaultConnectTimeout bounds each connection attempt and the initial ping.

## Functions

### func CheckViolation

```go
func CheckViolation(err error) (constraint string, ok bool)
```

CheckViolation reports whether err is a check constraint violation and returns the constraint's name.

### func ForeignKeyViolation

```go
func ForeignKeyViolation(err error) (constraint string, ok bool)
```

ForeignKeyViolation reports whether err is a foreign key violation and returns the constraint's name.

### func HealthCheck

```go
func HealthCheck(pool *pgxpool.Pool) health.Check
```

HealthCheck returns a readiness check that pings the database.

### func InTx

```go
func InTx(ctx context.Context, db Beginner, fn func(tx pgx.Tx) error) error
```

InTx runs fn in a read-write transaction with the server's default isolation level. See [InTxWithOptions](#InTxWithOptions).

### func InTxWithOptions

```go
func InTxWithOptions(ctx context.Context, db Beginner, opts pgx.TxOptions, fn func(tx pgx.Tx) error) error
```

InTxWithOptions runs fn in a transaction started with opts. It commits when fn returns nil. Otherwise it rolls back and returns fn's error unchanged, so callers can match domain errors with [errors.Is](https://pkg.go.dev/errors#Is). If fn panics, the transaction is rolled back and the panic continues.

Build tx-bound repositories inside fn (for example NewUserStore(tx)); never keep tx after fn returns. With [pgx.Serializable](https://pkg.go.dev/github.com/jackc/pgx/v5#Serializable), retry when [IsRetryable](#IsRetryable) reports true.

### func IsNoRows

```go
func IsNoRows(err error) bool
```

IsNoRows reports whether err means a query returned no rows, as from QueryRow(...).Scan. Repositories return their not-found domain error.

### func IsRetryable

```go
func IsRetryable(err error) bool
```

IsRetryable reports whether err is a serialization failure or deadlock, after which the whole transaction can be retried.

### func Migrate

```go
func Migrate(ctx context.Context, pool *pgxpool.Pool, fsys fs.FS) ([]int64, error)
```

Migrate applies every pending goose migration in the root of fsys (files such as 00001\_create\_users.sql) and returns the versions it applied, in order. It returns nil when fsys has no migrations or none are pending.

A PostgreSQL advisory lock serialises concurrent callers, so several instances can run Migrate at once. Apps run migrations from a separate command, never implicitly at startup (ADR-0017).

### func NotNullViolation

```go
func NotNullViolation(err error) (column string, ok bool)
```

NotNullViolation reports whether err is a not-null violation and returns the column's name.

### func Open

```go
func Open(ctx context.Context, url config.Secret, opts ...Option) (*pgxpool.Pool, error)
```

Open creates a connection pool for url and pings the database, so a wrong URL or unreachable server fails at startup. Errors never include the URL, which may contain a password.

Every query becomes an OpenTelemetry client span carrying the SQL text but never its arguments. Close the pool on shutdown:

	cleanup.Add("postgres", func(context.Context) error { pool.Close(); return nil })

### func UniqueViolation

```go
func UniqueViolation(err error) (constraint string, ok bool)
```

UniqueViolation reports whether err is a unique constraint violation and returns the constraint's name, so repositories can map it to a domain error such as ErrDuplicateEmail.

## Types

### type Beginner

```go
type Beginner interface {
	BeginTx(ctx context.Context, opts pgx.TxOptions) (pgx.Tx, error)
}
```

Beginner starts transactions. \*pgxpool.Pool and \*pgx.Conn implement it.

### type DBTX

```go
type DBTX interface {
	Exec(ctx context.Context, sql string, args ...any) (pgconn.CommandTag, error)
	Query(ctx context.Context, sql string, args ...any) (pgx.Rows, error)
	QueryRow(ctx context.Context, sql string, args ...any) pgx.Row
}
```

DBTX runs queries. \*pgxpool.Pool, \*pgxpool.Conn, \*pgx.Conn and pgx.Tx implement it, so repositories work with or without a transaction.

### type MigrationState

```go
type MigrationState struct {
	// Current is the highest applied version, 0 when none are applied.
	Current int64
	// Latest is the highest version in the migration files.
	Latest int64
	// Pending counts migration files not yet applied.
	Pending int
}
```

MigrationState describes the schema version against a set of migrations.

#### func Migrations

```go
func Migrations(ctx context.Context, pool *pgxpool.Pool, fsys fs.FS) (MigrationState, error)
```

Migrations reports the database's migration state for fsys, for readiness reports and doctor commands. It changes nothing.

### type Option

```go
type Option interface {
	// contains filtered or unexported methods
}
```

An Option configures [Open](#Open).

#### func WithApplicationName

```go
func WithApplicationName(name string) Option
```

WithApplicationName sets application\_name, shown in pg\_stat\_activity.

#### func WithConnectTimeout

```go
func WithConnectTimeout(d time.Duration) Option
```

WithConnectTimeout bounds each connection attempt and the ping in [Open](#Open). Default: [DefaultConnectTimeout](#DefaultConnectTimeout).

#### func WithMaxConnIdleTime

```go
func WithMaxConnIdleTime(d time.Duration) Option
```

WithMaxConnIdleTime closes connections idle longer than d. Default: 30 minutes.

#### func WithMaxConnLifetime

```go
func WithMaxConnLifetime(d time.Duration) Option
```

WithMaxConnLifetime closes connections older than d, so load moves to new database hosts after failover. Default: one hour.

#### func WithMaxConns

```go
func WithMaxConns(n int32) Option
```

WithMaxConns sets the maximum pool size. Default: pgx's default, the greater of 4 and the number of CPUs.

#### func WithMinConns

```go
func WithMinConns(n int32) Option
```

WithMinConns sets how many connections the pool keeps open when idle. Default: 0.

#### func WithTracerProvider

```go
func WithTracerProvider(tp trace.TracerProvider) Option
```

WithTracerProvider sets the provider for query spans. Default: the global OpenTelemetry provider.

