PostgreSQL backups
DataQI uses CloudNativePG (CNPG) External link; internet access required to manage its PostgreSQL clusters. When backups are enabled, CNPG provides:
- Continuous WAL archiving — individual transaction logs are streamed to the destination as they are written, providing a low recovery point objective (RPO).
- Scheduled base backups — periodic full backups taken on a configurable cron schedule.
- Point-in-time recovery (PITR) — any base backup combined with its WAL archive allows restoration to any point in time within the retention window.
Backups are disabled by default and can be configured independently per cluster.
How backups work
Section titled “How backups work”Each of the three managed CNPG clusters — pg-api, pg-audit, and pg-keycloak — has its own backup configuration block nested under databases.<cluster>.backup. This means you can configure different retention periods, schedules, or destination paths for each cluster, or enable backups for only a subset of them.
Backup is enabled for a cluster simply by providing a non-empty barmanObjectStore block. No separate enabled flag is needed.
The chart accepts any valid CNPG barmanObjectStore specification as a pass-through value. This means any storage backend supported by Barman Cloud works without chart changes — including Azure Blob Storage, AWS S3, Google Cloud Storage, and S3-compatible on-premises stores such as MinIO.
Configuration
Section titled “Configuration”Configure backups per cluster by adding a backup sub-block under the relevant database key. You only need to configure the clusters you want to back up:
databases: api: backup: retentionPolicy: "30d" # How long to retain base backups (default: 30d) schedule: "0 2 * * *" # Cron schedule for base backups (default: 02:00 UTC daily) barmanObjectStore: # Provider-specific configuration — see examples below audit: backup: retentionPolicy: "90d" # Audit data often needs longer retention schedule: "0 2 * * *" barmanObjectStore: # Can be a different destination to apiProvider examples
Section titled “Provider examples”Azure Blob Storage
Section titled “Azure Blob Storage”Create a Kubernetes secret containing your storage account credentials:
kubectl create secret generic pg-backup-creds \ --from-literal=storage-account=<account-name> \ --from-literal=storage-key=<account-key>Then configure the barmanObjectStore under each database you want to back up:
databases: api: backup: retentionPolicy: "30d" schedule: "0 2 * * *" barmanObjectStore: destinationPath: "https://<account>.blob.core.windows.net/<container>/pg-api" azureCredentials: storageAccount: name: pg-backup-creds key: storage-account storageKey: name: pg-backup-creds key: storage-key wal: compression: gzip data: compression: gzip audit: backup: retentionPolicy: "90d" # Example: longer retention for audit data schedule: "0 2 * * *" barmanObjectStore: destinationPath: "https://<account>.blob.core.windows.net/<container>/pg-audit" azureCredentials: storageAccount: name: pg-backup-creds key: storage-account storageKey: name: pg-backup-creds key: storage-key wal: compression: gzip data: compression: gzipAKS Workload Identity: If your cluster uses Azure Workload Identity, you can avoid a credentials secret entirely by annotating the CNPG service account with your managed identity client ID and replacing the
azureCredentialsblock withinheritFromAzureAD: true. The managed identity must have the Storage Blob Data Contributor role on the container.
AWS S3
Section titled “AWS S3”kubectl create secret generic pg-backup-creds \ --from-literal=ACCESS_KEY_ID=<key> \ --from-literal=ACCESS_SECRET_KEY=<secret>databases: api: backup: retentionPolicy: "30d" schedule: "0 2 * * *" barmanObjectStore: destinationPath: "s3://<bucket>/pg-api" s3Credentials: accessKeyId: name: pg-backup-creds key: ACCESS_KEY_ID secretAccessKey: name: pg-backup-creds key: ACCESS_SECRET_KEY wal: compression: gzip data: compression: gzipMinIO (on-premises / air-gapped)
Section titled “MinIO (on-premises / air-gapped)”For environments without public internet access, MinIO External link; internet access required provides an S3-compatible object store that can run entirely within your Kubernetes cluster or on bare metal. It supports full WAL archiving and PITR with no cloud dependency.
Deploy MinIO into your cluster first (for example, using the MinIO Operator External link; internet access required or a simple StatefulSet), then point barmanObjectStore at it using endpointURL:
kubectl create secret generic pg-backup-creds \ --from-literal=ACCESS_KEY_ID=<minio-access-key> \ --from-literal=ACCESS_SECRET_KEY=<minio-secret-key>databases: api: backup: retentionPolicy: "30d" schedule: "0 2 * * *" barmanObjectStore: destinationPath: "s3://<bucket-name>/pg-api" endpointURL: "http://minio.minio-ns.svc.cluster.local:9000" s3Credentials: accessKeyId: name: pg-backup-creds key: ACCESS_KEY_ID secretAccessKey: name: pg-backup-creds key: ACCESS_SECRET_KEY wal: compression: gzip data: compression: gzipTLS: If your MinIO instance is configured with TLS, use
https://inendpointURLand ensure the relevant CA certificate is trusted by the CNPG pods. See the custom CA bundle guide for details.
Verifying backups
Section titled “Verifying backups”Once backups are enabled and the clusters have started, you can inspect backup status using kubectl:
# List scheduled backup resourceskubectl get scheduledbackups -n <namespace>
# Inspect a specific cluster's backup statuskubectl get cluster pg-api -n <namespace> -o jsonpath='{.status.lastSuccessfulBackup}'
# View all completed backup objectskubectl get backups -n <namespace>A healthy cluster will show a lastSuccessfulBackup timestamp on the cluster status, and individual Backup objects will reach completed phase.
Retention and recovery
Section titled “Retention and recovery”The retentionPolicy field controls how many days of base backups are retained. WAL segments are retained automatically to cover the oldest available base backup.
For point-in-time recovery, refer to the CNPG recovery documentation External link; internet access required. Recovery is performed by bootstrapping a new cluster from an existing backup using the bootstrap.recovery stanza — this is outside the scope of the DataQI Helm chart and is performed directly via CNPG.