PgBouncer
PgBouncer does not expose a native Prometheus endpoint. The
pgbouncer-exporter sidecar connects to PgBouncer's admin
interface (the virtual pgbouncer database) and translates
SHOW STATS and SHOW POOLS output into 44 Prometheus
metrics with the pgbouncer_* prefix. The OpenTelemetry
Collector scrapes the exporter using the Prometheus receiver,
collecting metrics across connection pools, query throughput,
client wait times, and server utilization. This guide
configures the exporter, the Collector, and ships metrics
to base14 Scout.
Prerequisites
| Requirement | Minimum | Recommended |
|---|---|---|
| PgBouncer | 1.12 | 1.23+ |
| pgbouncer-exporter | 0.7.0 | latest |
| OTel Collector Contrib | 0.90.0 | latest |
| base14 Scout | Any | --- |
Before starting:
- PgBouncer must be accessible from the host running the exporter
- The exporter must be accessible from the host running the Collector
- A PgBouncer user listed in
stats_usersoradmin_users(see Access Setup) - Scout account and API credentials
- Scout Collector installed and configured (see Quick Start)
For Docker deployments, use edoburu/pgbouncer
(multi-architecture including ARM64) or bitnami/pgbouncer
with an explicit version tag. The Bitnami image does not
publish a latest tag.
What You'll Monitor
- Connection Pools: client active/waiting connections, server active/idle/used/testing/login connections, max wait time
- Traffic & Throughput: SQL transactions pooled, queries pooled, bytes sent/received, query duration
- Client Experience: client wait time, server in-transaction time, cancel requests
- Configuration State: max client connections, max user connections, pool size, database count
- Health:
pgbouncer_upstatus, free clients/servers, used clients/servers, cached DNS entries
Full metric reference: pgbouncer-exporter metrics
Access Setup
PgBouncer requires two configuration changes to support the exporter.
1. Create a monitoring user
Add the exporter's connecting user to stats_users in
pgbouncer.ini:
[pgbouncer]
stats_users = otel_monitor
ignore_startup_parameters = extra_float_digits
stats_usersgrants read-only access toSHOWcommandsignore_startup_parametersis required because the exporter's PostgreSQL driver sendsextra_float_digitsduring connection startup, which PgBouncer rejects by default
2. Add authentication
Add the monitoring user to userlist.txt:
"otel_monitor" "your_password"
3. Verify access
# Connect to PgBouncer admin interface
psql "postgres://otel_monitor:your_password@localhost:6432/pgbouncer?sslmode=disable" \
-c "SHOW STATS;"
No write permissions are needed. The exporter only reads pool and traffic statistics.
Configuration
pgbouncer-exporter
Run the exporter as a sidecar alongside PgBouncer:
docker run -d \
--name pgbouncer-exporter \
-p 9127:9127 \
prometheuscommunity/pgbouncer-exporter \
--pgBouncer.connectionString="postgres://${PGBOUNCER_USER}:${PGBOUNCER_PASSWORD}@pgbouncer-host:6432/pgbouncer?sslmode=disable"
The exporter listens on port 9127 and serves metrics at
/metrics.
OTel Collector
receivers:
prometheus:
config:
scrape_configs:
- job_name: pgbouncer
scrape_interval: 30s
static_configs:
- targets:
- ${env:PGBOUNCER_EXPORTER_HOST}:9127
processors:
resource:
attributes:
- key: environment
value: ${env:ENVIRONMENT}
action: upsert
- key: service.name
value: ${env:SERVICE_NAME}
action: upsert
batch:
timeout: 10s
send_batch_size: 1024
# Export to base14 Scout
exporters:
otlphttp/b14:
endpoint: ${env:OTEL_EXPORTER_OTLP_ENDPOINT}
tls:
insecure_skip_verify: true
service:
pipelines:
metrics:
receivers: [prometheus]
processors: [resource, batch]
exporters: [otlphttp/b14]
Environment Variables
PGBOUNCER_EXPORTER_HOST=localhost
ENVIRONMENT=your_environment
SERVICE_NAME=your_service_name
OTEL_EXPORTER_OTLP_ENDPOINT=https://<your-tenant>.base14.io
Verify the Setup
Start the exporter and Collector, then check for metrics within 60 seconds:
# Check exporter is serving metrics
curl -s http://localhost:9127/metrics \
| grep pgbouncer_up
# Expected: pgbouncer_up 1
# Check Collector logs for successful scrape
docker logs otel-collector 2>&1 | grep -i "pgbouncer"
Troubleshooting
pgbouncer_up showing 0
Cause: The exporter cannot connect to PgBouncer's admin interface.
Fix:
- Verify PgBouncer is running:
docker ps | grep pgbouncerorss -tlnp | grep 6432 - Test the connection string manually:
psql "postgres://otel_monitor:pass@localhost:6432/pgbouncer?sslmode=disable" - Confirm the user is listed in
stats_usersoradmin_usersinpgbouncer.ini - Check that
ignore_startup_parametersincludesextra_float_digits
Connection refused on port 9127
Cause: The exporter is not running or not reachable from the Collector.
Fix:
- Verify the exporter container is running:
docker ps | grep pgbouncer-exporter - Confirm port 9127 is exposed:
curl http://localhost:9127/metrics - Check firewall rules if the Collector runs on a separate host
No metrics appearing in Scout
Cause: Metrics are collected but not exported.
Fix:
- Check Collector logs for export errors:
docker logs otel-collector - Verify
OTEL_EXPORTER_OTLP_ENDPOINTis set correctly - Verify your Scout Collector is running
- Confirm the pipeline includes both the receiver and exporter
Exporter fails with "unsupported startup parameter"
Cause: ignore_startup_parameters is not set in
pgbouncer.ini.
Fix:
- Add
ignore_startup_parameters = extra_float_digitsto the[pgbouncer]section - Reload PgBouncer:
pgbouncer -Ror sendSIGHUP - Restart the exporter
FAQ
Does this work with PgBouncer in Kubernetes?
Yes. Deploy the exporter as a sidecar container in the
same pod as PgBouncer. Set the exporter's connection
string to localhost:6432 since both containers share
the pod network. Point the Collector's scrape target to
the pod IP or a headless service on port 9127.
How do I monitor multiple PgBouncer instances?
Add multiple targets to the scrape config:
receivers:
prometheus:
config:
scrape_configs:
- job_name: pgbouncer
scrape_interval: 30s
static_configs:
- targets:
- pgbouncer-exporter-1:9127
- pgbouncer-exporter-2:9127
Each PgBouncer instance needs its own exporter sidecar.
The instance label differentiates metrics from each
target.
Why is pgbouncer_up showing 0?
The exporter cannot reach PgBouncer's admin interface.
Common causes: the connecting user is not in stats_users,
ignore_startup_parameters does not include
extra_float_digits, or PgBouncer is not listening on the
expected port. See the
Troubleshooting section.
What pool mode should I use for monitoring?
The exporter works with all PgBouncer pool modes
(session, transaction, statement). Pool mode affects
how PgBouncer manages backend connections, not the
monitoring interface. The exporter connects to the virtual
pgbouncer database, which is independent of pool mode
settings for application databases.
What's Next?
- Create Dashboards: Explore pre-built dashboards or build your own. See Create Your First Dashboard
- Monitor More Components: Add monitoring for PostgreSQL, HAProxy, and other components
- Fine-tune Collection: Adjust
scrape_intervalbased on pool churn rate — high-traffic deployments may benefit from 15s intervals
Related Guides
- OTel Collector Configuration --- Advanced collector configuration
- Docker Compose Setup --- Run the Collector locally
- Kubernetes Helm Setup --- Production deployment
- PostgreSQL Monitoring --- Monitor the databases behind PgBouncer
- Creating Alerts --- Alert on PgBouncer metrics