# Top 4 Open Source Postgres Connection Poolers (2026)

> The best open-source Postgres connection poolers in 2026. Compare PgBouncer, Odyssey, PgDoorman, and PgDog — with our pick: PgBouncer if you want free, PgDog if you want a commercial vendor.

Adela | 2026-07-10 | Source: https://www.bytebase.com/blog/open-source-postgres-connection-pooler/

---

| Update History | Comment |
| -------------- | ------- |
| 2025/10/03 | Initial version. |
| 2026/07/10 | Remove cf-pgbouncer (archived by Cloudflare) and Supavisor. Add Odyssey and PgDoorman. Expand PgDog. Refresh all facts. |

> **Note:** This post is maintained by Bytebase, an open-source database governance platform. We update the post every year.

Postgres's connection model is the part that bites. Each client connection is a dedicated backend process with real memory and CPU cost, opening connections is expensive, and even idle sessions hold resources. Picking `max_connections` is guesswork: too low and your app queues, too high and the database burns RAM on connections that mostly sit idle.

A connection pooler sits between your apps and Postgres, reusing a small set of server connections across many clients.

![Before and after: 1,000 direct client connections blow past Postgres max_connections, while a connection pooler maps them onto 20 server connections](/content/blog/open-source-postgres-connection-pooler/connection-pooler.svg)

Here's a tour of the leading **open-source** options.

## PgBouncer

https://github.com/pgbouncer/pgbouncer

**What it is.** A lightweight, single-binary pooler that's been in production for years. It supports **session**, **transaction**, and **statement** pooling modes, per-user/per-database connection limits, and prepared statements in transaction mode. It's actively maintained — the 1.25.2 release (May 2026) fixed four CVEs in SCRAM and admin-console handling.

**Why it's popular:**

- Small footprint, deploys almost anywhere.
- Works with managed Postgres (RDS, AlloyDB, etc.) and on-prem clusters.
- Wired into many operators (CloudNativePG ships a `Pooler` CRD).

The caveat: PgBouncer is **single-threaded**. A busy instance bottlenecks on one CPU core; the standard remedy is several instances behind a load balancer. (Cloudflare archived its multi-tenant fork in June 2026 — upstream is the way.)

**Good fit for:** most apps that need stable concurrency control and simple operations.

## Odyssey

https://github.com/yandex/odyssey

**What it is.** A **multi-threaded** C pooler from Yandex, built because a single-threaded PgBouncer didn't survive Yandex-scale traffic. It does session and transaction pooling plus a richer request-routing layer, and it's proven in very large production setups — Yandex runs it in front of its managed Postgres fleet. v1.5.0 landed in January 2026.

**Why it scales:**

- Worker threads share the global connection pools, so one instance spreads across cores — no fleet of single-threaded processes each hoarding its own connections.
- Transaction pooling cleans up after clients: Odyssey tracks transaction state, and when a client vanishes mid-transaction it cancels the running query and rolls back the abandoned transaction before the connection is reused. Since v1.5.0, prepared statements survive transaction pooling by default (`pool_reserve_prepared_statement`).
- Operations at fleet scale: per-connection UUIDs for end-to-end log tracing, built-in Prometheus metrics, and auth that reaches beyond md5/SCRAM to PAM and LDAP, with full TLS on both sides.

The trade-off is complexity. Odyssey brings more knobs, its own configuration language, and documentation that's thinner than PgBouncer's — it assumes you have (or are) a platform team.

**Good fit for:** high-throughput workloads where PgBouncer saturates a core and you'd rather scale up one pooler than orchestrate a fleet.

## PgDoorman

https://github.com/ozontech/pg_doorman

**What it is.** A **multi-threaded Rust** pooler from Ozon, one of the largest e-commerce platforms in Russia — in production there for over three years across Go, .NET, Python, and Node.js workloads. It does session and transaction pooling under an MIT license; v3.11.0 shipped in June 2026. digoal, the prolific Chinese Postgres evangelist, [put it on the map](https://mp.weixin.qq.com/s/oWG3cxxatKTfEo__GFITHw) in July 2026.

**Why it stands out — transparent transaction pooling:**

- Prepared statements without driver surgery: anonymous statements are remapped to named ones, so backends reuse plans.
- One shared pool across all worker threads — no multi-instance fleet with skewed load.
- Admin console, graceful binary upgrades, Prometheus exporter, Patroni-assisted failover.

The caveat: it's deliberately narrow — no load balancing, sharding, or routing — and the transparency covers the protocol, not session semantics: `SET` and `LISTEN`/`NOTIFY` still break. (Its self-reported benchmarks run 3–4× ahead of PgBouncer, disclaimed by the project itself: "Benchmarks always lie to you.")

**Good fit for:** teams whose blocker is transaction pooling's compatibility tax, and who want pooling only — nothing else.

## PgDog

https://github.com/pgdogdev/pgdog

**What it is.** A **multi-threaded Rust** proxy that rolls **connection pooling**, **load balancing**, and **sharding** into one layer, backed by Y Combinator and $5.5M in funding. It succeeds **PgCat**, the Instacart-born pooler by the same author, and supports **online resharding** via logical replication. Releases ship weekly, and the project reports 2M+ queries per second across dozens of production deployments.

**Why it's different** — [a real SQL parser](https://pgdog.dev/blog/why-yet-another-connection-pooler) keeps the Postgres features other poolers make you give up:

- `SET` and Row-Level Security keep working: per-client session state is re-applied before each query.
- `LISTEN` / `NOTIFY` survive transaction pooling via in-process broadcast channels.
- Transparent prepared statements, one Tokio process across all cores, and a PgBouncer-style admin database plus OpenMetrics.

The caveat: the more the proxy does, the more of your traffic architecture lives inside it — and its AGPL-3.0 license is the most restrictive here.

**Good fit for:** teams that want one proxy for pooling, routing, and scale-out, and want a company on the other end of the pager. PgDog is the only option here with a commercial vendor behind it.

---

## Feature comparison

**Project**

|                       | PgBouncer | Odyssey      | PgDoorman | PgDog    |
| --------------------- | --------- | ------------ | --------- | -------- |
| **Language**          | C         | C            | Rust      | Rust     |
| **License**           | ISC       | BSD-3-Clause | MIT       | AGPL-3.0 |
| **GitHub stars**      | 4.2k      | 3.5k         | 0.3k      | 5.1k     |
| **Commercial vendor** | ❌        | ❌           | ❌        | ✅       |

**Pooling** — the last two rows are what transaction pooling usually breaks.

|  | PgBouncer | Odyssey | PgDoorman | PgDog |
| --- | --- | --- | --- | --- |
| **Modes** | Session, transaction, statement | Session, transaction | Session, transaction | Session, transaction |
| **Multi-core** | ❌ single-threaded | ✅ multi-threaded | ✅ multi-threaded, shared pool | ✅ multi-threaded |
| **Prepared statements** | ✅ opt-in (`max_prepared_statements`) | ✅ | ✅ transparent, with plan cache | ✅ |
| **Session state (`SET`, `LISTEN`/`NOTIFY`)** | ❌ | ❌ | ❌ | ✅ |

**Beyond pooling**

|                                 | PgBouncer            | Odyssey            | PgDoorman    | PgDog                |
| ------------------------------- | -------------------- | ------------------ | ------------ | -------------------- |
| **Built-in Prometheus metrics** | ❌ external exporter | ✅                 | ✅           | ✅ OpenMetrics       |
| **Load balancing / routing**    | ❌                   | ✅ request routing | ❌ by design | ✅                   |
| **Sharding**                    | ❌                   | ❌                 | ❌ by design | ✅ online resharding |

A ❌ in the last table isn't always a gap. PgDoorman deliberately stops at pooling — Ozon's position is that routing belongs in a different layer. The more rows a proxy fills in, the more of your traffic architecture lives inside it.

---

## Our pick

```mermaid
quadrantChart
    x-axis Battle-tested --> New generation
    y-axis Pooling only --> Routing / sharding
    quadrant-1 Full proxy, commercial
    quadrant-2 Scale-out veteran
    quadrant-3 The default
    quadrant-4 Modern focused pooler
    PgBouncer: [0.15, 0.15]
    Odyssey: [0.25, 0.75]
    PgDoorman: [0.8, 0.12]
    PgDog: [0.85, 0.85]
```

One pooler per quadrant — the four don't compete head-on. Pick your row (pool only, or also route and shard?), then your column (production mileage, or a modern engine?). Two choices cover most teams:

**Free: PgBouncer.** The default for a reason: small, proven, and wired into every managed Postgres and operator you're likely to touch. Its one real limit is the single thread, and the fix is well-trodden — a few instances behind a load balancer.

**Commercial: PgDog.** The only pooler here with a company behind it, and it earns the spot on merit: pooling, load balancing, and sharding in one multi-threaded proxy that keeps `SET`, Row-Level Security, and `LISTEN`/`NOTIFY` working under transaction pooling.

**Narrow constraints:** **Odyssey** when one PgBouncer core saturates, **PgDoorman** when transaction pooling keeps fighting your drivers. Both are open-source only — no vendor to call.

Whichever you pick, watch for:

- **Pooling mode.** Session maximizes compatibility, transaction wins concurrency but breaks session state, statement is rarely what you want.
- **Limits at the pooler.** Per-user and per-database caps protect Postgres from thundering herds.
- **Prepared statements.** All four now handle them at the protocol level — opt-in on PgBouncer (`max_prepared_statements`) — but test your own ORM rather than assuming.
- **HA, like any stateless proxy.** Multiple poolers behind a VIP or load balancer, with health checks and drain/reload flows.
- **The basics.** Right-size the pool, the client cap, and timeouts against actual concurrency — pools are per user/db/host tuple.

Treat the pooler as part of your capacity and SLO strategy: cap concurrency, keep transactions short, and watch pool saturation.