What happens
internal/database/database.go OpenPostgres calls sqlx.Open("postgres", url) and returns. database/sql then keeps its default of 2 idle connections. With a few dozen concurrent requests almost every request opens a new connection, runs its 2-4 statements and closes it again. Each new session costs a backend fork plus SCRAM-SHA-256 on the server (30-180 ms on a small container) and PBKDF2 in lib/pq on the client.
Measured (4 parallel pnpm install jobs, ~200 requests in flight): pg_stat_database.sessions grew by 0.8 per request; the proxy topped out at ~60 req/s with a warm tarball hit at p50 3.3 s (24 ms idle). A hit-only probe at concurrency 16 reproduced 61 req/s / p50 269 ms. Putting PgBouncer in front of Postgres (session mode) took the same probe to 186 req/s / p50 79 ms; the request-rate ceiling for small artifacts is ~1,000 req/s once the session cost is gone.
Suggestion
After sqlx.Open in OpenPostgres:
sqlDB.SetMaxOpenConns(32)
sqlDB.SetMaxIdleConns(32)
sqlDB.SetConnMaxIdleTime(5 * time.Minute)
sqlDB.SetConnMaxLifetime(30 * time.Minute)
What happens
internal/database/database.goOpenPostgrescallssqlx.Open("postgres", url)and returns.database/sqlthen keeps its default of 2 idle connections. With a few dozen concurrent requests almost every request opens a new connection, runs its 2-4 statements and closes it again. Each new session costs a backend fork plus SCRAM-SHA-256 on the server (30-180 ms on a small container) and PBKDF2 in lib/pq on the client.Measured (4 parallel
pnpm installjobs, ~200 requests in flight):pg_stat_database.sessionsgrew by 0.8 per request; the proxy topped out at ~60 req/s with a warm tarball hit at p50 3.3 s (24 ms idle). A hit-only probe at concurrency 16 reproduced 61 req/s / p50 269 ms. Putting PgBouncer in front of Postgres (session mode) took the same probe to 186 req/s / p50 79 ms; the request-rate ceiling for small artifacts is ~1,000 req/s once the session cost is gone.Suggestion
After
sqlx.OpeninOpenPostgres: