Skip to main content
The questions below cover the topics that come up most often from operators new to PGO and from teams moving production workloads onto Kubernetes. If you do not find an answer here, join the PGO community Discord or open a discussion on GitHub.
Cloud-managed services such as Amazon RDS, Google Cloud SQL, and Azure Database for PostgreSQL remove the operational burden of running a database — but they also remove control. You cannot access the underlying host, install arbitrary extensions, or tune kernel parameters. Pricing is typically higher per GB, and your data lives entirely within one cloud provider.PGO gives you a self-managed PostgreSQL cluster running inside your own Kubernetes cluster. You retain full control over the PostgreSQL configuration, the extensions you install, the storage class, and where your data and backups live. PGO automates the same operational concerns a managed service handles — provisioning, high availability, failover, backups, and minor-version updates — but on infrastructure you own.The trade-off is that you are responsible for keeping the Kubernetes cluster healthy and for upgrading PGO itself. For teams already running Kubernetes, the operational overhead is usually acceptable, and the cost and control advantages are significant.
Yes, but with important constraints. PGO expects the PostgreSQL container to include specific binaries and directory layouts it relies on: the postgres and pg_ctl binaries must be on the path, pgBackRest must be installed, and Patroni must be available as a Python module. The postgres UID (26) must match what the operator expects.In practice, most users either use the official Crunchy Data images or build a custom image FROM a Crunchy base image and add their additional tooling on top. Building from scratch is possible but requires careful matching of file paths, UID assignments, and installed packages to what PGO expects.You can set a custom image by supplying its full pull spec in spec.image on the PostgresCluster resource.
PGO creates a ClusterIP service for the primary and, when connection pooling is enabled, a separate service for pgBouncer. Neither is exposed outside the cluster by default.To enable external access, you have three main options:
  1. LoadBalancer service — Add a service override in your PostgresCluster spec or create a separate Service of type LoadBalancer that selects the primary pod label postgres-operator.crunchydata.com/role=master.
  2. NodePort — Expose the existing service on a specific port on every node.
  3. Kubernetes Ingress or Gateway API — Route TCP traffic through an Ingress controller or Gateway that supports PostgreSQL’s protocol (e.g., nginx with TCP proxying, or a Gateway API implementation with TCPRoute).
See the TLS guide for how to manage certificates when exposing PostgreSQL outside the cluster.
PGO is a stateless Kubernetes controller. All cluster state is stored in the PostgresCluster custom resource and in standard Kubernetes objects (Secrets, ConfigMaps, StatefulSets, Services). When the operator pod restarts, it re-reads the desired state from those objects and reconciles any drift. Running PostgreSQL clusters are not affected by a transient operator restart.If you run multiple operator replicas with leader election enabled (PGO_CONTROLLER_LEASE_NAME), the active leader can be replaced within a few seconds with no impact on running clusters.
Yes. By default, PGO runs in cluster-wide mode and watches PostgresCluster resources in every namespace. You can restrict it to a subset of namespaces using environment variables:
  • PGO_TARGET_NAMESPACE — limits PGO to a single namespace.
  • PGO_TARGET_NAMESPACES — limits PGO to a comma-separated list of namespaces.
Leave both variables unset to watch all namespaces. See supported platforms for the full configuration table.You can also deploy multiple instances of the PGO operator, each watching different namespaces, if you need stricter isolation.
PGO schedules backups automatically using the schedule defined in spec.backups.pgbackrest.repos[].schedules. To trigger a one-time manual backup outside that schedule, create a PostgresClusterBackup annotation on the cluster or use the pgBackRest stanza management commands directly from inside the backup pod.The most straightforward approach is to exec into the pgbackrest container and run the backup command:
See the backups guide for complete scheduling and repository configuration.
PGO works with any StorageClass that provides ReadWriteOnce PersistentVolumes. For production workloads, prefer a StorageClass backed by local NVMe or network-attached SSD storage that guarantees low latency and consistent IOPS.Recommended starting points by cloud:
  • AWS EKS — gp3 (the default in most clusters). Prefer io1 or io2 for write-heavy workloads.
  • GKE — pd-ssd for SSD-backed persistent disks.
  • AKS — managed-premium for Azure Premium SSD.
  • On-premises — Local path provisioner for single-node clusters; Rook-Ceph, Longhorn, or a commercial SAN driver for multi-node clusters.
If you want to use the AutoGrowVolumes feature gate to automatically expand volumes when they fill up, the StorageClass must have allowVolumeExpansion: true. Check your StorageClass definition:
The recommended approach depends on how much downtime you can tolerate.Minimal downtime — pgBackRest restore from a backup:
  1. Take a base backup of the source database using pg_basebackup or pg_dump.
  2. For a logical dump: restore it into a PGO-managed cluster using psql after the cluster starts.
  3. For a physical restore: use pgBackRest stanza bootstrapping to seed a new cluster from an external pgBackRest repository.
Zero downtime — logical replication:
  1. Provision a new PGO cluster of the same major PostgreSQL version.
  2. Set up logical replication from the source to the new cluster.
  3. Cut traffic over once replication lag is near zero.
  4. Disable replication and remove the old source.
See the disaster recovery guide for details on point-in-time restore and standby clusters that can also be used to seed a new PGO cluster.
Physical restore requires that the source and destination PostgreSQL major versions match exactly. For migrations across major versions, use a logical dump-and-restore approach or the PGUpgrade custom resource after migration.

Still have questions?

Troubleshooting guide

Step-by-step diagnosis for the most common PGO issues.

Architecture overview

Understand how PGO, Patroni, pgBackRest, and pgBouncer work together.

Create a cluster

Walk through provisioning your first PostgresCluster from scratch.

Feature gates reference

Enable alpha and beta capabilities not available by default.