Released: 29 June 2026
This release of EDB CloudNativePG Cluster is part of the LTS series for 1.25.x. EDB will continue providing LTS releases in the 1.25.x series according to our Long-Term Support policy.
EDB CloudNativePG Cluster 1.25 approaches End-of-Life.
Users are encouraged to start planning their upgrade to a newer minor version before that date.
This release of EDB CloudNativePG Cluster includes the following:
Highlights
The cluster reference is now immutable on the Database, Pooler,
Publication, Subscription, and ScheduledBackup resources. Pointing one
of these objects at a different cluster has no well-defined semantics and
previously left the controllers in an inconsistent state; the update is now
rejected at the API server via a CEL validation rule.
(#10743)
Enhancements
| Description | Addresses |
|---|---|
Added a label selector to the | #8996 |
| The operator now emits a `Warning` `PrimaryStatusCheckFailed` event on the `Cluster` when the primary pod is `Ready` from the kubelet perspective but the operator's `/pg/status` check fails and failover is deferred, giving users visibility into the deferral via `kubectl describe cluster`. | #10509 |
| The operator now reloads a CNPG-i plugin automatically when its pods are rolled: it watches the `EndpointSlices` backing plugin `Services` and re-enqueues every cluster using the plugin once the new pods become `Ready`, so an upgraded plugin is picked up without waiting for the next resync. | #10836 |
Security Fixes
| Description | Addresses |
|---|---|
| #10774, GHSA-x8c2-3p4r-v9r6 |
| #10724, GHSA-w3gf-xc94-wvmj |
Changes
| Description | Addresses |
|---|---|
| Updated the default PostgreSQL version to 18.4. | #10719 |
| Updated the Kubernetes versions used to test the operator on public cloud providers. | #10720, #10563, #11033 |
Bug Fixes
| Description | Addresses |
|---|---|
| Fixed `spec.postgresql.parameters` accepting keys that are not valid PostgreSQL parameter names, which could inject arbitrary directives into `postgresql.conf`; key names are now validated by the webhook. | #11029 |
| Fixed declarative `Database`, `Publication`, and `Subscription` objects reporting a stale primary-side status forever after their cluster was demoted to a replica; the controller now re-checks the replica condition and watches the `Cluster` so a demotion is detected promptly. | #10871 |
| Fixed non-sequential pod names (for example `-1`, `-3`) caused by the instance serial counter being advanced before the corresponding `Job` and PVCs were created; the bump is now persisted only after those resources exist. | #10491 |
Fixed a switchover deadlock when a WAL-archiver plugin was enabled on an existing cluster: with | #11032, #11059 |
| Fixed a cluster staying in `Setting up primary` indefinitely when the instance-creation Job exhausted its backoff limit; the operator now detects the terminal Job failure and marks the cluster unrecoverable, naming the failed Job and pointing to its logs. | #11035 |
Fixed deletion of a | #10853 |
| Fixed a conflicting duplicate `Database` or `Subscription` with a `delete` reclaim policy dropping the PostgreSQL object owned by the surviving CR; the drop is now gated on a recorded reconciliation. | #10870 |
Fixed the | #10834 |
Fixed resource leaks when concurrent | #10747 |
| Fixed role reconciliation clearing the password on a PostgreSQL role when the referenced Secret could not be fetched; the role is now left untouched until the Secret becomes available, and per-action errors are aggregated for better visibility. | #10053 |
Fixed a bootstrap failure where a metrics-exporter setup error (commonly a duplicate-key race with the controller) rolled back | #10749 |
| Fixed a `ScheduledBackup` controller loop that occurred when a `Backup` was created but its status patch never landed; the controller now adopts an existing `Backup` for the next iteration instead of looping on `AlreadyExists`. | #10612 |
| Fixed bootstrap log handling so that all named log pipes (`postgres`, `postgres.csv`, and `postgres.json`) get consumers during `WithActiveInstance`, preventing regular files from being created in place of the named pipes. | #10043 |
Fixed generation of invalid IPv6 URLs by wrapping the address in square brackets.Contributed by @Infinoid. | #10682 |
| Fixed an external cluster plugin still being treated as active when its configuration set `enabled: false`. | #10932 |
Fixed a race during bootstrap recovery from an object store where the restore job could read a stale | #10818 |
Fixed a cache race during cluster creation when the server and client CA resolve to the same Secret (the default): a stale informer cache triggered a redundant | #10989 |
| Fixed the `pg_basebackup` bootstrap path overwriting or failing on a pre-existing `PGDATA` (for example after a replica Pod restart) by enforcing the same pre-flight directory check already applied by the other bootstrap methods; this also protects statically provisioned PVCs from being silently overwritten. | #11006 |
Fixed the | #10421 |
Fixed stale certificate data and partial reads after an external server's Secret was rotated (for example a CA bundle shrinking from two certificates to one): the file is now written atomically, so libpq always reads either the old or the new value, never a mix.Contributed by @Anand-240. | #10975 |
Fixed plugin connectivity to use the plugin | #10921 |
| Fixed excessive operator log noise from the per-request `Cluster` create/update validation webhook messages, now logged at `debug` instead of `info`. | #10984 |
| Fixed a first-primary bootstrap deadlock where a status-patch conflict after the data PVC was created but before the initialization Job was started left the orphan Pending PVC counted as an instance, blocking the bootstrap gate; the PVC-state reconciler now recreates the bootstrap Job reusing the assigned serial. | #11039 |
Fixed external cluster names and secret selector references being joined into filesystem paths without validation, letting a | #11045 |
Fixed a declarative | #11071 |
| Fixed a volume snapshot backup being discarded on a transient instance-manager connection error (for example a dial timeout from a brief pod-network disruption) during the finalize step, even when its snapshots were already provisioned; such network errors are now retried instead of treated as terminal. | #11069 |
| Fixed a replica switchover losing its `status.demotionToken` when a reconcile was requeued between storing the token and cleaning up the transition metadata (for example a cleanup patch failing against a flaky webhook); the empty no-change token is no longer patched back over the stored value. | #11075 |
Fixed | #10972 |
Fixed an unbounded memory leak in | #10976 |