Overview
PgDog is a high-performance PostgreSQL connection pooler, load balancer, and sharding proxy written in Rust. It sits transparently in front of one or more PostgreSQL instances and appears to clients as a standard PostgreSQL server — no application code changes required, only a connection string update. PgDog parses SQL queries to automatically route writes (INSERT, UPDATE, DELETE, DDL) to a primary backend and distribute SELECT queries across replicas. Works with any PostgreSQL-compatible backend including the Control Plane PostgreSQL and PostgreSQL Highly Available templates, or any external PostgreSQL endpoint.
Architecture
- PgDog workload — Stateless proxy that multiplexes client connections into a smaller pool of real backend connections. Scales horizontally; each replica maintains its own connection pool.
- pgdog.toml — Main configuration rendered as a secret and mounted at startup. Defines backend databases, pool settings, timeouts, and load balancing strategy.
- users.toml — Credentials configuration rendered as a separate secret. Defines which users can connect to PgDog and which backend databases they map to.
What Gets Created
- Standard PgDog Workload — Stateless proxy workload listening on port 6432.
- Identity & Policy — Identity for the workload with access to credential secrets.
- Secrets — Two opaque secrets: one for
pgdog.toml(database and pooling config) and one forusers.toml(user credentials).
This template does not create a GVC or a PostgreSQL instance. Deploy it into an existing GVC and point it at an existing PostgreSQL backend.
Prerequisites
This template has no external prerequisites. To install, follow the instructions for your preferred method:UI
Browse, install, and manage templates visually
CLI
Manage templates from your terminal
Terraform
Declare templates in your Terraform configurations
Pulumi
Declare templates in your Pulumi programs
Configuration
The defaultvalues.yaml for this template:
Backend Databases
Thedatabases list defines the PostgreSQL backends PgDog proxies. Each entry maps to a [[databases]] block in pgdog.toml. Multiple entries sharing the same name form a cluster — PgDog routes writes to primary backends and distributes reads across replica backends.
role | Behavior |
|---|---|
primary | Receives all write queries (INSERT, UPDATE, DELETE, DDL) |
replica | Receives read queries (SELECT) distributed by the load balancing strategy |
auto | PgDog detects the role via pg_is_in_recovery() at connection time |
host to {release-name}-postgres.{gvc}.cpln.local.
Using with the PostgreSQL Highly Available template — Point the primary entry at the HA proxy ({release-name}-postgres-ha-proxy.{gvc}.cpln.local) and add replica entries using the replicaDirect hostnames (replica-{n}.{release-name}-postgres-ha.{location}.{gvc}.cpln.local).
Users
Theusers list defines which clients can connect to PgDog. Each entry maps to a [[users]] block in users.toml. The database field must match a name from the databases list.
name and password to authenticate incoming clients, then uses the same credentials to connect to the backend PostgreSQL server.
Connection Pooling
| Parameter | Default | Description |
|---|---|---|
pooling.mode | transaction | Pool mode: transaction or session |
pooling.defaultPoolSize | 10 | Maximum real Postgres connections per pool |
pooling.minPoolSize | 1 | Minimum idle connections kept open |
pooling.workers | 2 | Async threads; recommended value is 2× vCPU count |
| Pool Mode | Description |
|---|---|
transaction | Backend connection held only for the duration of a transaction, then returned to the pool. Best for most web and API workloads. Not compatible with SET variables, temporary tables, or advisory locks. |
session | Backend connection held for the entire client session. Compatible with all Postgres features. Increase defaultPoolSize to match expected concurrent client count. |
Load Balancing
| Strategy | Description |
|---|---|
least_active_connections | Routes reads to the replica with the fewest active connections. Recommended for most workloads. |
round_robin | Distributes reads evenly across all replicas in rotation. |
random | Selects a replica at random for each read query. |
readWriteSplit: include_primary allows the primary to also serve reads when no replicas are available.
Timeouts
All timeout values are in milliseconds.| Parameter | Default | Description |
|---|---|---|
timeouts.connect | 5000 | Time to establish a backend connection |
timeouts.checkout | 5000 | Max time a client waits for a free pool connection |
timeouts.idle | 60000 | Idle backend connections closed after this duration |
timeouts.query | 0 | Per-query timeout; 0 disables it |
Admin Database
PgDog exposes an internal admin database for stats and introspection.Access
internalAccess.type— Controls which workloads can reach PgDog internally:same-gvc,same-org,workload-list, ornone.publicAccess.enabled— Whentrue, Control Plane provisions a public TCP load balancer. The assigned hostname (e.g.pgdog-name-hash.cpln.app:6432) is visible in the Control Plane console or viacpln workload get <name> -o yaml.publicAccess.address— Optional custom domain to attach when public access is enabled.
Scaling
PgDog is stateless and scales horizontally by increasingreplicas. Each replica maintains its own connection pool — scale pooling.defaultPoolSize down proportionally when adding replicas to avoid overloading the backend with too many open connections.
Logging
Connecting
Applications connect to PgDog exactly as they would connect to PostgreSQL — PgDog implements the full PostgreSQL wire protocol.| Setting | Value |
|---|---|
| Host | {release-name}-pgdog.{gvc}.cpln.local |
| Port | 6432 |
| Database | A name from your databases list |
| Username | A name from your users list |
| Password | The matching password from your users list |
Important Notes
- PgDog does not manage PostgreSQL — it is a proxy only. Deploy a PostgreSQL backend separately before pointing PgDog at it.
- Port 6432, not 5432 — PgDog listens on port 6432. Update application connection strings accordingly.
- Transaction mode and session features — If your application uses
SETvariables, prepared statements, temporary tables, or advisory locks, usepooling.mode: sessioninstead oftransaction. - Admin password — Always set
admin.passwordexplicitly. Omitting it causes PgDog to generate a random password at each restart, making the admin database unreachable across restarts. - Scaling and pool sizing — Each PgDog replica maintains its own pool. When scaling
replicas, reducepooling.defaultPoolSizeproportionally to avoid opening too many total connections to the backend.
External References
PgDog Documentation
Official PgDog configuration and architecture reference
PgDog GitHub
Source code and issue tracker
PostgreSQL Template
Single-instance PostgreSQL template for use with PgDog
PostgreSQL Highly Available Template
HA PostgreSQL with Patroni — primary + replicas for PgDog read/write splitting