Production-ready PostgreSQL deployment with support for standalone and streaming replication architectures, structured
access controls, TLS, External Secrets Operator, optional replication slots, and production hardening controls.
Key Features
Standalone and replication — Single instance or primary with streaming replicas
Automatic initialization — Init scripts, extensions, and custom configuration
S3 backup — Scheduled backups to S3-compatible storage via CronJob
Metrics — Prometheus exporter with ServiceMonitor
Security — Non-root containers, TLS support with private-key permission normalization, structured pg_hba.conf CIDRs, NetworkPolicy controls, and ServiceAccount token control
Replication slots — Optional physical slots with WAL retention limits for safer replica catch-up behavior
External Secrets Operator — Optional external-secrets.io/v1 resources for auth, TLS, and backup credentials
Persistent storage — Configurable PVCs with storage class selection
Security Scan
Framework
Score
MITRE + NSA + SOC2
93%
Security posture is strong. Remaining findings are documented product exceptions for opt-in NetworkPolicy and
PostgreSQL’s writable runtime filesystem.
Architecture
Standalone
Single PostgreSQL instance with persistent storage and optional S3 backup.
Replication
Primary with streaming replicas, read-only service, and backup CronJob.
The chart does not install External Secrets Operator and does not create a SecretStore or ClusterSecretStore.
Enable this only when the operator and referenced store already exist.
Production Path
The default install remains intentionally suitable for local development and disposable test clusters. A production
deployment should explicitly set existing Secrets or External Secrets, storage, resources, config.allowedClientCIDRs,
config.allowedReplicationCIDRs, TLS, metrics, backup, and NetworkPolicy behavior.
Use the structured CIDR lists first. config.pgHbaEntries and raw config.pgHba remain escape hatches for advanced
cases, but production baselines should not depend on a full raw pg_hba.conf override.
Replication slots are disabled by default for compatibility. If replication.slots.enabled=true, also set WAL limits
such as replication.wal.maxSlotWalKeepSize so a stalled replica cannot retain unbounded WAL.
Operational Notes
The chart keeps internal health checks, metrics, and built-in backup on PostgreSQL’s standard postgres database.
If a reused PVC contains a valid data directory but is missing the default postgres database, the primary pod repairs that database during startup before normal readiness checks rely on it.
auth.database remains the application bootstrap database. It is created only on first initialization of a fresh data directory.
Set initdb.runDefaultScript=false when custom or externally managed init scripts should run without the chart-generated application and replication user bootstrap script.
docker-entrypoint-initdb.d scripts only run when the data directory is empty. Existing PVCs keep their current roles and databases during upgrades.
Dual-stack Networking
PostgreSQL Services accept Kubernetes dual-stack configuration. By default, both service.ipFamilyPolicy and service.ipFamilies are unset and the chart inherits whatever the cluster advertises (matching prior behavior). Setting them propagates to every chart-managed Service: client, primary, replicas, metrics, and the headless StatefulSet services.
PreferDualStack is the safer choice for clusters that may be single- or dual-stack: omit ipFamilies and the cluster auto-populates whatever it supports. Set ipFamilies explicitly only when the cluster is configured for both families — the Kubernetes API rejects an explicit family the cluster does not advertise. RequireDualStack enforces both.
Configuration Reference
This reference covers the complete values.yaml surface for the PostgreSQL chart.
Core
Parameter
Type
Default
Description
architecture
string
standalone
Deployment architecture: standalone or replication.
nameOverride
string
""
Override the chart name.
fullnameOverride
string
""
Override the full release name.
commonLabels
object
{}
Extra labels added to all rendered resources.
clusterDomain
string
cluster.local
Kubernetes cluster domain used in generated DNS names.
Image
Parameter
Type
Default
Description
image.repository
string
docker.io/library/postgres
PostgreSQL runtime image repository.
image.tag
string
"18.6-trixie"
PostgreSQL runtime image tag.
image.pullPolicy
string
IfNotPresent
Image pull policy for PostgreSQL containers.
imagePullSecrets
array
[]
Optional image pull secrets for private registries.
Authentication
Parameter
Type
Default
Description
auth.postgresPassword
string
""
PostgreSQL superuser password when not using an existing secret.
auth.database
string
app
Application database created on first bootstrap.
auth.username
string
app
Application username created on first bootstrap.
auth.password
string
""
Application user password when not using an existing secret.
auth.replicationUsername
string
replicator
Replication username used by read replicas.
auth.replicationPassword
string
""
Replication password when not using an existing secret.
auth.existingSecret
string
""
Existing secret containing PostgreSQL passwords.
auth.existingSecretPostgresPasswordKey
string
postgres-password
Secret key holding the PostgreSQL superuser password.
auth.existingSecretUserPasswordKey
string
user-password
Secret key holding the application user password.
auth.existingSecretReplicationPasswordKey
string
replication-password
Secret key holding the replication user password.
PostgreSQL Configuration
Parameter
Type
Default
Description
config.localAuthMethod
string
scram-sha-256
Authentication method for local Unix-socket connections.
config.allowedClientCIDRs
array
["0.0.0.0/0", "::/0"]
CIDRs allowed to connect to regular PostgreSQL databases.
config.allowedReplicationCIDRs
array
["0.0.0.0/0", "::/0"]
CIDRs allowed to connect to the replication pseudo-database.
config.preset
string
none
Optional PostgreSQL tuning preset: none, small, medium, or large.
config.postgresql
string
""
Raw postgresql.conf content appended after generated settings.
config.pgHbaEntries
array
[]
Structured pg_hba.conf entries appended after generated defaults.
config.pgHba
string
""
Raw pg_hba.conf content appended after generated rules.
TLS
Parameter
Type
Default
Description
tls.enabled
boolean
false
Enable TLS for PostgreSQL and internal clients.
tls.existingSecret
string
""
Existing secret containing server TLS material.
tls.certFilename
string
tls.crt
Certificate filename inside the TLS secret.
tls.keyFilename
string
tls.key
Private key filename inside the TLS secret.
tls.caFilename
string
ca.crt
CA certificate filename inside the TLS secret.
tls.sslMode
string
require
libpq SSL mode used by internal probes, replication, and exporter.
tls.minProtocolVersion
string
TLSv1.2
Minimum accepted PostgreSQL TLS protocol version.
tls.volumePermissions.enabled
boolean
false
Copy TLS material to an owned emptyDir and restrict the private key to 0600.
Initialization
Parameter
Type
Default
Description
initdb.runDefaultScript
boolean
true
Run the chart-generated app database, app user, and replication user script.
initdb.scripts
object
{}
Additional scripts written into docker-entrypoint-initdb.d.
initdb.existingConfigMap
string
""
Existing ConfigMap mounted into docker-entrypoint-initdb.d.
Standalone
Parameter
Type
Default
Description
standalone.resourcesPreset
string
small
Optional resource preset for standalone mode.
standalone.persistence.enabled
boolean
true
Enable a PVC for standalone mode.
standalone.persistence.storageClass
string
""
StorageClass for the standalone PVC.
standalone.persistence.accessModes
array
["ReadWriteOnce"]
Access modes for the standalone PVC.
standalone.persistence.size
string
8Gi
PVC size for standalone mode.
standalone.resources
object
{}
Explicit resource requests and limits for standalone mode.
Replication - Primary
Parameter
Type
Default
Description
replication.primary.resourcesPreset
string
small
Optional resource preset for the primary pod.
replication.primary.persistence.enabled
boolean
true
Enable PVCs for the primary StatefulSet.
replication.primary.persistence.storageClass
string
""
StorageClass for primary PVCs.
replication.primary.persistence.accessModes
array
["ReadWriteOnce"]
Access modes for primary PVCs.
replication.primary.persistence.size
string
20Gi
PVC size for the primary pod.
replication.primary.resources
object
{}
Explicit resource requests and limits for the primary pod.
replication.primary.probes.requireWritable
boolean
true
In replication mode, require primary readiness to confirm the pod is not in recovery mode.
Replication - Read Replicas
Parameter
Type
Default
Description
replication.readReplicas.resourcesPreset
string
small
Optional resource preset for replica pods.
replication.readReplicas.replicaCount
integer
2
Number of asynchronous read replica pods.
replication.readReplicas.persistence.enabled
boolean
true
Enable PVCs for replica StatefulSets.
replication.readReplicas.persistence.storageClass
string
""
StorageClass for replica PVCs.
replication.readReplicas.persistence.accessModes
array
["ReadWriteOnce"]
Access modes for replica PVCs.
replication.readReplicas.persistence.size
string
20Gi
PVC size for each replica.
replication.readReplicas.resources
object
{}
Explicit resource requests and limits for replica pods.
Enable opinionated topology spread defaults in replication mode.
replication.scheduling.topologyKey
string
kubernetes.io/hostname
Topology key used by the default replication spread rules.
Service
Parameter
Type
Default
Description
service.type
string
ClusterIP
Service type for PostgreSQL client access.
service.annotations
object
{}
Annotations applied to the client Service.
service.primaryAnnotations
object
{}
Annotations applied to the dedicated primary Service.
service.replicasAnnotations
object
{}
Annotations applied to the dedicated replicas Service.
service.port
integer
5432
PostgreSQL listener port.
service.metricsPort
integer
9187
Metrics port exposed when metrics are enabled.
service.ipFamilyPolicy
string
omitted
Service IP family policy: SingleStack, PreferDualStack, or RequireDualStack. Omit for cluster default.
service.ipFamilies
array
omitted
Ordered list of IP families (IPv4, IPv6). Omit for cluster default.
Metrics
Parameter
Type
Default
Description
metrics.enabled
boolean
false
Enable the postgres_exporter sidecar.
metrics.resourcesPreset
string
small
Optional resource preset for postgres_exporter.
metrics.service.annotations
object
{}
Annotations applied to metrics Services.
metrics.image.repository
string
quay.io/prometheuscommunity/postgres-exporter
Metrics sidecar image repository.
metrics.image.tag
string
"v0.18.0"
Metrics sidecar image tag.
metrics.image.pullPolicy
string
IfNotPresent
Image pull policy for postgres_exporter.
metrics.resources
object
{}
Explicit resource requests and limits for postgres_exporter.
metrics.serviceMonitor.enabled
boolean
false
Create a ServiceMonitor for Prometheus Operator.
metrics.serviceMonitor.interval
string
30s
Scrape interval for the ServiceMonitor.
metrics.serviceMonitor.labels
object
{}
Extra labels applied to the ServiceMonitor.
Backup
Parameter
Type
Default
Description
backup.enabled
boolean
false
Enable the built-in backup CronJob.
backup.schedule
string
"0 3 * * *"
Backup schedule in cron format.
backup.suspend
boolean
false
Suspend backup execution.
backup.concurrencyPolicy
string
Forbid
CronJob concurrency policy.
backup.successfulJobsHistoryLimit
integer
3
Successful backup Jobs retained by the CronJob.
backup.failedJobsHistoryLimit
integer
3
Failed backup Jobs retained by the CronJob.
backup.backoffLimit
integer
1
Job backoff limit for backup execution.
backup.archivePrefix
string
postgresql
Prefix used in generated backup archive names.
backup.resources
object
requests 100m/128Mi, limits 500m/512Mi
Resources applied to backup dump and upload containers.
backup.images.uploader.repository
string
docker.io/helmforge/mc
Uploader image repository for S3 copies.
backup.images.uploader.tag
string
"1.0.0"
Uploader image tag.
backup.images.uploader.pullPolicy
string
IfNotPresent
Pull policy for the uploader image.
backup.images.postgresql.repository
string
docker.io/library/postgres
PostgreSQL client image used for backup jobs.
backup.images.postgresql.tag
string
"18.6-trixie"
PostgreSQL client image tag used for backup jobs.
backup.images.postgresql.pullPolicy
string
IfNotPresent
Pull policy for the PostgreSQL backup image.
backup.s3.endpoint
string
""
S3-compatible endpoint URL.
backup.s3.bucket
string
""
Target bucket name.
backup.s3.prefix
string
postgresql
Optional key prefix inside the bucket.
backup.s3.createBucketIfNotExists
boolean
true
Create the bucket automatically when it does not exist.
backup.s3.existingSecret
string
""
Existing secret containing backup access and secret keys.
backup.s3.existingSecretAccessKeyKey
string
access-key
Secret key name for the S3 access key.
backup.s3.existingSecretSecretKeyKey
string
secret-key
Secret key name for the S3 secret key.
backup.s3.accessKey
string
""
Inline S3 access key when not using an existing secret.
backup.s3.secretKey
string
""
Inline S3 secret key when not using an existing secret.
backup.database.pgDumpAllArgs
string
"--clean --if-exists"
Extra arguments passed to pg_dumpall.
NetworkPolicy
Parameter
Type
Default
Description
networkPolicy.enabled
boolean
false
Create a NetworkPolicy for PostgreSQL pods.
networkPolicy.ingress.allowSameNamespace
boolean
true
Allow ingress from the same namespace.
networkPolicy.ingress.extraFrom
array
[]
Additional ingress from rules appended to the generated policy.
networkPolicy.egress.enabled
boolean
false
Add explicit egress rules to the NetworkPolicy.
networkPolicy.egress.allowDNS
boolean
true
Allow DNS egress on TCP/UDP 53.
networkPolicy.egress.allowSameNamespacePostgreSQL
boolean
true
Allow PostgreSQL egress to same-namespace pods.
networkPolicy.egress.allowHTTPS
boolean
true
Allow HTTPS egress for S3-compatible backup endpoints.
networkPolicy.egress.extraTo
array
[]
Additional egress to rules appended to the policy.
Pod Disruption Budget
Parameter
Type
Default
Description
pdb.enabled
boolean
false
Enable a PodDisruptionBudget outside replication defaults.
pdb.minAvailable
integer
1
Minimum available pods when the PDB is enabled.
pdb.maxUnavailable
string
""
Maximum unavailable pods when the PDB is enabled.
Service Account
Parameter
Type
Default
Description
serviceAccount.create
boolean
false
Create a dedicated ServiceAccount.
serviceAccount.name
string
""
Override the ServiceAccount name.
serviceAccount.annotations
object
{}
Annotations applied to the ServiceAccount.
serviceAccount.automountServiceAccountToken
boolean
false
Mount Kubernetes API credentials into workload and backup pods.
Probes
Parameter
Type
Default
Description
livenessProbe.enabled
boolean
true
Enable the liveness probe.
livenessProbe.initialDelaySeconds
integer
60
Liveness probe initial delay.
livenessProbe.periodSeconds
integer
20
Liveness probe period.
livenessProbe.timeoutSeconds
integer
5
Liveness probe timeout.
livenessProbe.failureThreshold
integer
6
Liveness probe failure threshold.
readinessProbe.enabled
boolean
true
Enable the readiness probe.
readinessProbe.initialDelaySeconds
integer
20
Readiness probe initial delay.
readinessProbe.periodSeconds
integer
10
Readiness probe period.
readinessProbe.timeoutSeconds
integer
5
Readiness probe timeout.
readinessProbe.failureThreshold
integer
6
Readiness probe failure threshold.
startupProbe.enabled
boolean
true
Enable the startup probe.
startupProbe.initialDelaySeconds
integer
10
Startup probe initial delay.
startupProbe.periodSeconds
integer
10
Startup probe period.
startupProbe.timeoutSeconds
integer
5
Startup probe timeout.
startupProbe.failureThreshold
integer
60
Startup probe failure threshold.
Scheduling and Security
Parameter
Type
Default
Description
podSecurityContext.fsGroup
integer
999
Filesystem group applied to PostgreSQL pods.
podSecurityContext.fsGroupChangePolicy
string
OnRootMismatch
Filesystem group change policy.
podSecurityContext.seccompProfile.type
string
RuntimeDefault
Seccomp profile applied at pod level.
securityContext.runAsUser
integer
999
Runtime UID for PostgreSQL containers.
securityContext.runAsGroup
integer
999
Runtime GID for PostgreSQL containers.
securityContext.runAsNonRoot
boolean
true
Require containers to run as non-root.
securityContext.allowPrivilegeEscalation
boolean
false
Disable privilege escalation.
securityContext.readOnlyRootFilesystem
boolean
false
Keep the root filesystem writable for PostgreSQL runtime needs.
securityContext.capabilities.drop
array
["ALL"]
Linux capabilities dropped from PostgreSQL containers.
podLabels
object
{}
Extra labels applied to PostgreSQL pods.
podAnnotations
object
{}
Extra annotations applied to PostgreSQL pods.
annotations
object
{}
Extra annotations applied to chart-managed resources that support them.
nodeSelector
object
{}
Node selector applied to PostgreSQL pods.
tolerations
array
[]
Tolerations applied to PostgreSQL pods.
affinity
object
{}
Explicit affinity rules.
topologySpreadConstraints
array
[]
Explicit topology spread constraints.
priorityClassName
string
""
PriorityClass applied to PostgreSQL pods.
terminationGracePeriodSeconds
integer
120
Termination grace period for PostgreSQL pods.
Extra
Parameter
Type
Default
Description
extraEnv
array
[]
Extra environment variables injected into PostgreSQL containers.
extraVolumes
array
[]
Extra volumes appended to PostgreSQL pods.
extraVolumeMounts
array
[]
Extra volume mounts appended to PostgreSQL containers.
External Secrets Operator
Parameter
Type
Default
Description
externalSecrets.enabled
boolean
false
Render ExternalSecret resources.
externalSecrets.apiVersion
string
external-secrets.io/v1
ExternalSecret API version.
externalSecrets.refreshInterval
string
1h
Refresh interval used by rendered ExternalSecrets.
externalSecrets.secretStoreRef.name
string
""
Existing SecretStore or ClusterSecretStore name.
externalSecrets.auth.enabled
boolean
false
Manage the PostgreSQL auth Secret through ESO.
externalSecrets.tls.enabled
boolean
false
Manage the TLS Secret through ESO.
externalSecrets.backup.enabled
boolean
false
Manage the backup S3 credential Secret through ESO.
Upgrade Notes
PostgreSQL 18.6 is the August 2026 security and bug-fix release; upstream did
not publish 18.5 because of a post-wrap regression. Back up the cluster and
review the
official PostgreSQL 18.6 release notes
before upgrading. A dump and restore is not required from an earlier PostgreSQL
18 release, but test extensions, authentication, replication, and application
queries in staging.
for breaking changes in values structure. Always back up your data before upgrading.
When switching from standalone to replication, set auth.replicationPassword before upgrading
PVC resize requires the storage class to support volume expansion (allowVolumeExpansion: true)
Metrics sidecar changes may cause a pod restart during upgrade
Common Issues
Pod stuck in CrashLoopBackOff
Usually caused by incorrect auth.postgresPassword on upgrade. PostgreSQL does not re-initialize
auth when the data directory already exists. Check logs with kubectl logs <pod> and verify the
password matches the existing data.
Slow replication sync
For large databases, initial replica sync can take time. Increase readReplicas.resources and ensure the storage
class provides adequate IOPS. Monitor replication lag with the Prometheus exporter (pg_replication_lag metric).
Using with connection poolers
For high-connection workloads, deploy PgBouncer alongside PostgreSQL. Point your application to PgBouncer and
configure it to connect to the PostgreSQL service.