Files
common/database/pgdb/CLAUDE.md
Ask Bjørn Hansen 614cbf8097 feat(pgdb): add PG* environment variable fallback in OpenPool
When no DATABASE_URI or config file is found, fall through to
pgxpool.ParseConfig("") which natively reads standard PG* variables
(PGHOST, PGUSER, PGPASSWORD, PGDATABASE, etc.). This removes
unnecessary ceremony in CI and container environments where PG* vars
are already set.
2026-02-21 00:34:09 -08:00

152 lines
3.9 KiB
Markdown

# pgdb - Native PostgreSQL Connection Pool
Primary package for PostgreSQL connections using native pgx pool (`*pgxpool.Pool`). Provides better performance and PostgreSQL-specific features compared to `database/sql`.
## Usage
### Basic Example
```go
import (
"context"
"go.ntppool.org/common/database/pgdb"
)
func main() {
ctx := context.Background()
// Open pool with default options
pool, err := pgdb.OpenPool(ctx, pgdb.DefaultPoolOptions())
if err != nil {
log.Fatal(err)
}
defer pool.Close()
// Use the pool for queries
row := pool.QueryRow(ctx, "SELECT version()")
var version string
row.Scan(&version)
}
```
### With Custom Config File
```go
pool, err := pgdb.OpenPoolWithConfigFile(ctx, "/path/to/database.yaml")
```
### With Custom Pool Settings
```go
opts := pgdb.DefaultPoolOptions()
opts.MaxConns = 50
opts.MinConns = 5
opts.MaxConnLifetime = 2 * time.Hour
pool, err := pgdb.OpenPool(ctx, opts)
```
## Configuration Format
### Recommended: Nested Format (database.yaml)
```yaml
postgres:
host: localhost
port: 5432
user: myuser
pass: mypassword
name: mydb
sslmode: prefer
```
### Legacy: Flat Format (backward compatible)
```yaml
host: localhost
port: 5432
user: myuser
pass: mypassword
name: mydb
sslmode: prefer
```
## Configuration Options
### PoolOptions
Defaults match [pgxpool defaults](https://pkg.go.dev/github.com/jackc/pgx/v5/pgxpool#Config):
- `ConfigFiles` - List of config file paths to search (default: `database.yaml`, `/vault/secrets/database.yaml`)
- `MinConns` - Minimum connections (default: 0)
- `MaxConns` - Maximum connections (default: 4)
- `MaxConnLifetime` - Connection lifetime (default: 1 hour)
- `MaxConnIdleTime` - Idle timeout (default: 30 minutes)
- `HealthCheckPeriod` - Health check interval (default: 1 minute)
For higher connection limits, set via `PoolOptions` or URI query parameter `?pool_max_conns=25`.
### PostgreSQL Config Fields
- `host` - Database host (required)
- `user` - Database user (required)
- `pass` - Database password
- `name` - Database name (required)
- `port` - Port number (default: 5432)
- `sslmode` - SSL mode: `disable`, `allow`, `prefer`, `require`, `verify-ca`, `verify-full` (default: `prefer`)
## Environment Variables
- `DATABASE_URI` - PostgreSQL connection URI (takes precedence over all other methods)
- `DATABASE_CONFIG_FILE` - Override config file location
- Standard `PG*` variables (`PGHOST`, `PGUSER`, `PGPASSWORD`, `PGDATABASE`, `PGPORT`, `PGSSLMODE`, etc.) - used as fallback when no config file is found; parsed natively by pgx
### URI Format
Standard PostgreSQL URI format:
```
postgresql://user:password@host:port/database?sslmode=require&pool_max_conns=10
```
Pool settings can be included in the URI query string:
- `pool_max_conns`, `pool_min_conns`
- `pool_max_conn_lifetime`, `pool_max_conn_idle_time`
- `pool_health_check_period`
When using `DATABASE_URI`, pool settings come from the URI. Since `PoolOptions` defaults match pgxpool defaults, behavior is consistent whether using URI or config files.
Example with CloudNativePG:
```yaml
# Mount the secret's 'uri' key as DATABASE_URI
env:
- name: DATABASE_URI
valueFrom:
secretKeyRef:
name: mydb-app
key: uri
```
## When to Use
**Use `pgdb.OpenPool()`** (this package) when:
- You need native PostgreSQL features (LISTEN/NOTIFY, COPY, etc.)
- You want better performance
- You're writing new PostgreSQL code
**Use `database.OpenDB()`** (sql.DB) when:
- You need database-agnostic code
- You're using SQLC or other tools that expect `database/sql`
- You need to support both MySQL and PostgreSQL
## Security
This package avoids password exposure by:
1. Never constructing DSN strings with passwords
2. Setting passwords separately in pgx config objects
3. Validating all configuration before connection
## See Also
- `database/` - Generic sql.DB support for MySQL and PostgreSQL
- pgx documentation: https://github.com/jackc/pgx