Overview
PgDog is a high-performance PostgreSQL connection pooler, load balancer, and query router 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. It works with any PostgreSQL-compatible backend, including the Control Plane PostgreSQL and PostgreSQL Highly Available templates, or any external PostgreSQL endpoint.
Every credential comes from a secret you create before installing. Nothing sensitive passes through Helm values, so no password lands in the release, the rendered manifest, the stored workload spec, or the logs.
Architecture
- PgDog workload — Stateless proxy that multiplexes client connections into a smaller pool of real backend connections, routes writes to a primary, and distributes reads across replicas. Listens on port
6432. - Config secret — The static half of
pgdog.toml: general settings and the[[databases]]backends, rendered by the chart and mounted read-only. It holds no credentials. - Startup script secret — PgDog reads credentials only from files on disk and has no environment-variable interpolation, so a startup script assembles the final
pgdog.tomlandusers.tomlinside the container at boot from your prerequisite secrets, then execs PgDog. That is what keeps the credentials out of the Helm release. - Identity & policy — Grants the workload
revealon exactly the secrets it needs: the two chart-created ones, the admin password secret, and each pooled user’s credentials secret.
What Gets Created
- Standard PgDog Workload —
RELEASE_NAME-pgdog, a stateless proxy serving TCP on port6432. - Config Secret —
RELEASE_NAME-pgdog-config, an opaque secret holding the credential-free basepgdog.toml. - Startup Script Secret —
RELEASE_NAME-pgdog-startup, an opaque secret holding the script that assembles the config at container start. - Identity & Policy —
RELEASE_NAME-pgdog-identityandRELEASE_NAME-pgdog-policy, grantingrevealon the two chart secrets plus every prerequisite secret you referenced, and nothing else.
This template creates no secret that contains a credential. Your pooled-user and admin secrets are yours, which means uninstalling the release never destroys them.
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
Every secret you reference must exist before you install. Secrets are org-level, so no GVC flag is involved.1
Create one credentials secret per pooled user
A dictionary secret holding exactly two keys — Set
username and password. PgDog authenticates incoming clients with this pair and opens backend connections with it, so it must be a real PostgreSQL role on the backend:users[0].credentialsSecretName to the name you used. Because the username travels inside the secret, you can point this straight at the secret your backend already uses — see Pooled Users.2
Create the admin password secret
An opaque secret with encoding Set
plain, whose payload is the password for PgDog’s admin database:admin.passwordSecretName to the name you used. Use printf, not echo — echo appends a newline, which cannot be carried in a TOML value. The startup script detects a trailing newline and fails at boot with that message rather than starting a proxy that rejects every admin login.3
Read a secret back later
-o yaml is required. Without it the command prints the secret’s metadata table rather than its contents:Installation
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
ready roughly 25 seconds after install, once the startup script has assembled the config from your secrets and PgDog is listening on port 6432.
Upgrading From 1.0.0
Version1.1.0 moved every credential out of Helm values. 1.0.0 shipped working defaults — a pooled-user password and an admin password published in the public template repository — and PgDog is precisely the thing applications put in their connection strings, so those values were the product rather than internal plumbing.
To upgrade an existing install:
1
Create the secrets
Follow Prerequisites. Put the credentials your applications already use into the pooled-user secret so existing connection strings keep working, and pick a fresh admin password — the old one was a published default.
2
Drop the removed keys from your values
Remove
users[].name, users[].password and admin.password. Set users[].credentialsSecretName and admin.passwordSecretName instead, and rename resources.cpu and resources.memory to resources.maxCpu and resources.maxMemory if you had overridden them.3
Upgrade
The upgrade replaces the single stateless replica. Client connections are dropped and reconnect against the new one; there is no data to migrate.
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.
Using with the PostgreSQL template — Set
host to RELEASE_NAME-postgres. That workload is stateful, so its short name resolves inside the GVC; the fully qualified RELEASE_NAME-postgres.GVC_NAME.cpln.local works too.
Using with the PostgreSQL Highly Available template — Point the primary entry at the HA proxy (RELEASE_NAME-postgres-ha-proxy) and add replica entries using the replicaDirect hostnames (replica-N.RELEASE_NAME-postgres-ha.LOCATION.GVC_NAME.cpln.local).
Pooled Users
Each entry inusers maps to a [[users]] block in users.toml. Only the routing target is a value — the username and password both come from the dictionary secret named by credentialsSecretName:
credentialsSecretName secret holds. Pointing both templates at one secret was tested end to end: PgDog reads only the username and password keys and ignores the extra database key that PostgreSQL stores alongside them.
To pool a second user, create a second dictionary secret and add a second entry — one secret per entry:
Two entries may name the same secret, which is how you route one PostgreSQL role to two backend databases. The duplicate is deduplicated in the policy, so the secret appears as a single
reveal target. There is deliberately no way to put two users in one secret — a secret holds one username/password pair.Connection Pooling
The chart’s validation also accepts a third value,
statement, which upstream PgDog documents but which has not been verified end to end on this platform. Stay on transaction or session unless you are prepared to test it yourself.Timeouts
All timeout values are in milliseconds.Load Balancing
readWriteSplit: include_primary allows the primary to also serve reads.
Admin Database
PgDog exposes an internal admin database for stats and introspection. The names are ordinary values; the password is a prerequisite secret:reveal on a pooled user’s credentials cannot also reach the admin database. Both directions were verified — the pooled user’s password is refused on the admin database, and the admin password is refused on a pooled database.
Connect from a workload inside the GVC with any PostgreSQL client:
SHOW CLIENTS, SHOW POOLS and the other PgDog admin commands are available on that session.
Access
internalAccess.type— Controls which workloads can reach PgDog internally:same-gvc(default),same-org,workload-list, ornone. Withworkload-list, name each caller ininternalAccess.workloadsas//gvc/GVC_NAME/workload/WORKLOAD_NAME.publicAccess.enabled— Whentrue, Control Plane provisions a public TCP load balancer on port6432and assigns a canonical*.cpln.apphostname automatically. Read it fromstatus.canonicalEndpointincpln workload get RELEASE_NAME-pgdog --gvc GVC_NAME -o yaml.publicAccess.address— Optional custom domain to attach when public access is enabled. It names an existing Control Plane domain resource.
Give the public endpoint time to come up. Flipping
publicAccess.enabled on took 255 seconds to accept its first external connection in testing — longer than the 30–150 seconds most templates take. Budget anywhere from 30 seconds to about 5 minutes, and do not read a refused connection in the first few minutes as a broken setting.Scaling
PgDog is stateless and scales horizontally by raisingreplicas. Each replica keeps its own connection pool, so reduce pooling.defaultPoolSize proportionally when adding replicas — otherwise the backend sees replicas × defaultPoolSize connections. The template ships and was tested at a single replica.
Logging
Connecting
Applications connect to PgDog exactly as they would connect to PostgreSQL — PgDog implements the full PostgreSQL wire protocol.
Example connection string, with the username and password taken from your credentials secret:
Important Notes
- Create the prerequisite secrets before installing. A missing one wedges the deployment with no log output at all — Prerequisites gives the one command that diagnoses it.
- PgDog does not manage PostgreSQL — it is a proxy only. Deploy a backend before pointing PgDog at it.
- Port 6432, not 5432 — update application connection strings accordingly.
- The in-GVC hostname must be fully qualified —
RELEASE_NAME-pgdog.GVC_NAME.cpln.local. The short name does not resolve for this workload. - Transaction mode drops session state — if your application relies on
SETvariables, temporary tables, or advisory locks, usepooling.mode: session. - Each replica keeps its own pool — when raising
replicas, lowerpooling.defaultPoolSizeproportionally, or the backend seesreplicas × defaultPoolSizeconnections. - Rotating a credential needs a restart — the config files are assembled once at container start, so run
cpln workload force-redeployment RELEASE_NAME-pgdog --gvc GVC_NAMEafter changing a secret’s contents. - Enabling public access can take several minutes to take effect — measured at 255 seconds. Re-test before concluding the knob is broken.
- Uninstall leaves your secrets in place — they are yours, created outside the release. Only the two chart-created config secrets are removed.
External References
PgDog Documentation
Official PgDog configuration and architecture reference
users.toml Reference
How PgDog maps pooled users onto backend databases
PgDog GitHub
Source code and issue tracker
PgDog Template
View the source files, default values, and chart definition
PostgreSQL Template
Single-instance PostgreSQL template for use with PgDog
PostgreSQL Highly Available Template
HA PostgreSQL with Patroni — primary and replicas for PgDog read/write splitting