Skip to content

fix(db): replace lib/pq with pgx for connection pooler compatibility#6209

Open
brandonros wants to merge 1 commit intowoodpecker-ci:mainfrom
brandonros:fix/replace-libpq-with-pgx
Open

fix(db): replace lib/pq with pgx for connection pooler compatibility#6209
brandonros wants to merge 1 commit intowoodpecker-ci:mainfrom
brandonros:fix/replace-libpq-with-pgx

Conversation

@brandonros
Copy link

Summary

Fixes #6097

Replace github.com/lib/pq with github.com/jackc/pgx/v5/stdlib as the PostgreSQL driver.

lib/pq uses PostgreSQL's extended query protocol with unnamed prepared statements for all parameterized queries. This is incompatible with connection poolers (pgBouncer, pgcat) in transaction pooling mode — the pooler can route different clients' Parse/Bind messages to the same server connection, causing:

pq: bind message supplies 4 parameters, but prepared statement "" requires 1

pgx supports simple query protocol via the DSN parameter default_query_exec_mode=simple_protocol, which avoids prepared statements entirely and is fully compatible with transaction pooling.

Changes

  • server/store/datastore/init.go / init_cgo.go — Swap lib/pq import for pgx/v5/stdlib
  • server/store/datastore/engine.go — Map "postgres" driver name to "pgx" (pgx/stdlib registers under "pgx")
  • server/store/datastore/migration/migration_test.go — Update imports and driver names
  • go.mod / go.sum — Add pgx/v5, remove direct lib/pq dependency

Why pgx

  • Drop-in replacement via pgx/stdlib (implements database/sql interface — XORM works without changes)
  • Supports default_query_exec_mode=simple_protocol to avoid prepared statements
  • lib/pq is in maintenance mode; its author recommends migrating to pgx
  • Other Go projects (Gitea, etc.) have made the same migration for the same reason

Impact

  • Users connecting directly to PostgreSQL (no pooler): no behavior change
  • Users with session pooling mode: no behavior change
  • Users with transaction pooling mode (pgBouncer, pgcat): append ?default_query_exec_mode=simple_protocol to their WOODPECKER_DATABASE_DATASOURCE to resolve the error

Performance note

Simple protocol sends parameters as text (not binary) and cannot reuse prepared statement query plans. For Woodpecker's workload (simple CRUD queries), the difference is negligible.

🤖 Generated with Claude Code

lib/pq uses PostgreSQL's extended query protocol with unnamed prepared
statements for all parameterized queries, which is incompatible with
connection poolers (pgBouncer, pgcat) in transaction pooling mode.

Switch to pgx/stdlib which supports simple query protocol via the
DSN parameter `default_query_exec_mode=simple_protocol`, avoiding
prepared statements entirely.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error fetching repository list. pq: bind message supplies 4 parameters, but prepared statement "" requires 1

1 participant