Skip to content

Much higher per-query CPU overhead compared to pgbouncer #791

@frangz

Description

@frangz

Hi team,

We're running pgdog on EC2 alongside PostgreSQL 14 as a connection pooler (replacing pgbouncer for some services). We're seeing significantly higher CPU usage per query than expected, even with query_parser = "off".

Configuration

  • pgdog version: v0.1.30
  • Platform: Amazon Linux 2, i4i.24xlarge (96 vCPUs), x86_64
  • Connection: localhost
  • Workers: tested with both 2 and 6 (same per-query cost)
  • Pools: 15 database pools, transaction mode, each with user authentication
  • query_parser: off
  • read_write_split: not set (single local server per pool, no role assigned)

Relevant config

[general]
host = "0.0.0.0"
port = 6432
openmetrics_port = 9090
workers = 2

connect_timeout = 3000
idle_timeout = 30000
server_lifetime = 300000
client_login_timeout = 60000

log_connections = false
log_disconnections = false

query_parser = "off"

[tcp]
keepalive = true
time = 300000

Sample database definition

[[databases]]
name = "api"
host = "localhost"
port = 5432
database_name = "database"
pooler_mode = "transaction"
pool_size = 150
min_pool_size = 30

We have 15 similar pools.

Observed CPU usage

Queries/s CPU (%) CPU per qps
400 25% 0.063%
2,000 76% 0.038%
4,000 220% 0.055%
  • CPU correlates with query throughput, not with client connection count — spikes in connected clients with stable query rates do not affect CPU.
  • Changing workers from 6 to 2 made no difference to CPU at the same query rate.
  • Per-thread CPU (via top -H) shows 10–20% per tokio worker thread.

Comparison with pgbouncer

On the same instance, pgbouncer handles the full production workload:

Pooler Queries/s CPU (%) CPU per qps
pgbouncer 7,000 50% 0.007%
pgbouncer 30,000 200% 0.007%
pgdog 4,000 220% 0.055%

Expected vs actual

Your benchmarks show pgdog with 2 workers achieving 100k+ tps at ~75% CPU on a Ryzen 7 5800X — roughly 0.00075% CPU per query. Our observed cost is ~70x higher than that benchmark, despite using query_parser = "off" and connecting via localhost.

Impact

At our peak production traffic of 30k queries/s, linear extrapolation suggests pgdog would consume ~1,650% CPU (16+ cores). This makes it impractical as a pgbouncer replacement at our scale.

Questions

  • Is there additional per-query processing that happens even with query_parser = "off"?
  • Could 15 pool definitions with per-pool user authentication contribute to the overhead?
  • Are there any configuration options to reduce per-query CPU cost?
  • Anything we are doing wrong?

Metadata

Metadata

Assignees

No one assigned

    Labels

    cannot reproduce...yetSomething somewhere isn't computing and we don't know why

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions