Managed PostgreSQL
Understand CloudNativePG, asynchronous replicas, PgBouncer, TLS and staged logical recovery.
PostgreSQL 17 and 18 are part of the managed database development baseline introduced in self-hosted alpha.37. Controller installation is a separate operator task. The placement, pooling, TLS and monitoring described here follow current development source; check the exact release before relying on newer behavior. This page does not announce a production deployment.
CloudNativePG owns the members#
Hakopod records the scoped resource, immutable revision, operation and allocation in its PostgreSQL control database. Its Go worker reconciles an owned CloudNativePG cluster. CloudNativePG manages the PostgreSQL members; native observations identify the actual primary and replicas.
Standalone has one member. The current source supports a primary and one to six replicas for clustered configurations. Replication is asynchronous by default, so recent acknowledged writes can be lost after a primary failure. Two replicas on the same physical host do not make that host redundant.
schema_version = 1
name = "orders"
engine = "postgresql"
version = "17"
mode = "cluster"
replicas = 1
shards = 1
cpu = "500m"
memory = "1Gi"
storage_gib = 10
[tls]
mode = "required"
[placement]
spread = "nodes"
This requests two data members on separate eligible nodes. Each gets a 10Gi data volume. Admission includes an extra member-sized working allocation and other operational overhead. spread = "zones" instead needs separate reported zones; labels alone do not establish physical independence.
Direct routes and PgBouncer#
Use read_write for the primary service and read_only for a replica service. Replica reads can lag. Existing sessions must reconnect after failover and must not blindly retry an uncertain commit.
Optional PgBouncer adds pooled_read_write and, when configured with replicas, pooled_read_only. A database may use one to three pooler instances per route. Each pooler requests 250m CPU and 256Mi; reservation also includes runtime and replacement overhead. Poolers are supporting processes, not additional PostgreSQL replicas.
[pooling]
mode = "session"
instances = 2
max_client_connections = 200
default_pool_size = 10
read_only = true
This creates two poolers for each of the write and replica routes: four steady poolers. Session pooling retains a server connection for a client session. Transaction mode returns it after a transaction and requires compatible use of session variables, temporary tables and LISTEN. PgBouncer does not read arbitrary SQL to decide whether it belongs on the primary.
The pooling policy is immutable after creation. Select a direct route or a session pool for features that need a stable session. See the PgBouncer feature matrix.
Bind a service with verified TLS#
[services.api.bindings.DATABASE_URL]
managed_database = "DATABASE_ID"
protocol = "postgres"
endpoint = "read_write"
The runtime resolves application credentials and public trust for the approved service. Controller/bootstrap credentials stay separate. Clients verify the endpoint hostname and database CA. Poolers also verify their backend certificates and roles; a replica route does not grant a separate read-only account.
The public CA is available with hakopod database trust DATABASE_ID. Renewal must update the served identity and application trust, then verify new physical connections. Read the security guide before configuring a driver.
Logical backup and staged upgrades#
Managed backup captures a custom-format logical archive of the app database, then encrypts and verifies the stored bytes. This does not provide continuous WAL recovery or installation-wide point-in-time recovery.
Restore into a separate empty compatible database. PostgreSQL 17-to-18 migration uses this same logical recovery path. Downgrades and unknown source versions are rejected. The target runs restoration with the restricted application role; it cannot import global administrators from an archive.
Inspect the recovered schema and application behavior before recording inspection and reviewing the application's connection replacement. Account for source writes after capture. Imported Docker archives must match the expected custom format, major version and reviewed checksum.
Evidence and operator prerequisites#
The current guide records native development passes for both pooling modes, member/pooler replacement, replica write rejection, renewal, application trust and separate-target recovery. Those tests ran on Kubernetes nodes sharing one physical VM. They establish neither physical zone independence nor a performance guarantee, and they do not verify changes made after the tested source.
Use the pinned CloudNativePG controller, owned storage and the named development cluster for development acceptance. Upgrading the Hakopod binary does not install controllers. Start with the baseline release guide, then match current installation requirements to the release you choose. The architecture and recovery guides explain the shared durable operations.