Documentation navigation
CNPG Cluster Has No WAL Recovery Point
Runbook for a CNPG cluster that has a base backup but no WAL recovery point — the silent failure where the dashboard looks green (a backup timestamp exists) but recovery will fail. This is the root cause of the 2026-07 prd-par01 incident: every base backup looked healthy right up until recovery was attempted and WALs 015/016/017 were found never to have archived.
Meaning
A CNPG backup is two inseparable parts: a base snapshot (barman-cloud-backup) and continuous WAL archiving (barman-cloud-wal-archive). Recovery from a base backup requires WALs covering the checkpoint onward — without them, recovery fails.
cnpg_collector_last_available_backup_timestamp— epoch of the last successful base backup.> 0means a base backup exists.cnpg_collector_first_recoverability_point— epoch of the earliest point the cluster can be PITR-recovered to. Requires a base backup and WALs archived past that point. Absent (not 0) when archiving never produced a point.
The alert fires when a base backup exists (last_available_backup_timestamp > 0) but no recovery point exists (first_recoverability_point > 0 is absent) — using unless because the metric is absent, not zero, when archiving never produced a point. for: 2h rides out the transient window right after a backup before the first WAL recovery point appears.
The max by (job, k8s_cluster_name, environment, namespace) collapses to the primary's value (CNPG only updates these metrics on the primary; replicas report 0). The metrics are already scraped into Mimir — no chart PR is needed.
Impact
- The base backup cannot be recovered. Despite a green backup timestamp, a restore will fail when WAL replay hits the missing segment. This is the most dangerous CNPG failure: oncall assumes the cluster is protected when it is not.
- Every restore attempt wastes time discovering the gap mid-recovery; in an incident this is time you do not have.
- If the PVC is destroyed before WAL archiving is fixed, the data since the last recoverable point (possibly never) is lost.
Diagnosis
The alert labels carry k8s_cluster_name, environment, namespace, job (the CNPG cluster name). From the alert, note all of them.
The WAL-archive pipeline and remediation are identical to 01-cnpg-backup-failure.md. Use its Diagnosis section end-to-end:
- Step 3 — check WAL archive health (
first_recoverability_pointvia Mimir); check the primary pod's WAL archive sidecar logs (kubectl logs <primary> -c postgres | grep -i 'wal.*archive\|barman'). - Step 4 — check egress (the most common root cause — IPv6
::/0missing for Scaleway S3 blocked WALs for days on prd-par01 in the 2026-07 incident).
Confirm the absence directly via Mimir (port-forward synapse-server-mimir-gateway in monitoring-system, header X-Scope-OrgID: corti):
# The base backup exists (> 0)
QUERY1='max by (job, k8s_cluster_name, environment, namespace) (cnpg_collector_last_available_backup_timestamp{job="<job>", k8s_cluster_name="<cluster>"})'
# The recovery point is ABSENT (no result) when broken
QUERY2='max by (job, k8s_cluster_name, environment, namespace) (cnpg_collector_first_recoverability_point{job="<job>", k8s_cluster_name="<cluster>"})'
If QUERY1 returns a value > 0 but QUERY2 returns no result, WAL archiving is broken — this alert's condition.
Check the primary pod's WAL archive sidecar logs directly:
export KUBECONFIG=~/.kube/<cluster>.yaml
NS=<namespace>
PRIMARY=$(kubectl -n $NS get cluster <job> -o jsonpath='{.status.currentPrimary}')
kubectl -n $NS logs $PRIMARY -c postgres --tail=200 | grep -i 'wal.*archive\|barman'
Look for could not upload WAL file / barman-cloud-wal-archive: connection refused — the WAL sidecar cannot reach the object store.
Mitigation
Step 1 — Activate PIM
Activate the required Azure Privileged Identity Management roles before touching production (MultiTenantEuOnlyAccessPimRoles / DevOpsPimRoles / Platform Team (privileged)), as in 03-kafka/01-consumer-lag.md.
Step 2 — Fix WAL-archive egress
Follow 01-cnpg-backup-failure.md Mitigation step 2 — the root cause is almost always egress. WALs use the same object-store endpoint as the base backup; if base backups succeed but WALs do not, the endpoint resolves to an IPv6 address that the egress NetworkPolicy does not allow (the 2026-07 prd-par01 root cause). The durable fix is a chart PR adding ::/0 egress (cnpg-cluster chart PR #2868); do not kubectl patch (ArgoCD self-heal reverts it).
Once egress is fixed, the primary's WAL sidecar catches up and first_recoverability_point appears. The alert clears within the for: 2h window.
Step 3 — If the cluster is lost and recovery is needed
If the PVCs were destroyed before WAL archiving was fixed, the base backups are unrecoverable. Follow 01-cnpg-backup-failure.md Mitigation step 4 (fresh initdb, last resort) — the cluster must be recreated empty and the application owners rebuild data from upstream. Do not attempt recovery from the unrecoverable base backup.
Verify
- The alert clears once
cnpg_collector_first_recoverability_pointappears (is no longer absent) sustained for thefor: 2hwindow. - Confirm via the Mimir
QUERY2above — it returns a value > 0 once WALs are archiving. - The primary pod's WAL sidecar logs show successful
barman-cloud-wal-archiveuploads.
Notes
- Relationship to
01-cnpg-backup-failure.md— that runbook fires whenlast_available_backup_timestamp == 0(no base backup at all); this one fires when a base backup exists but WALs are not archiving (the silent "green but unrecoverable" state). The backup pipeline, diagnosis, and mitigation are shared. - Production-only — matches the chart alert.
- Silent failure — the base backup timestamp looks healthy; only the absence of
first_recoverability_pointreveals it. This is why the alert usesunless(the metric is absent, not 0, when broken). - Metric already collected —
cnpg_collector_first_recoverability_pointandcnpg_collector_last_available_backup_timestampare scraped from the CNPGpostgres_exportersidecar. No chart PR required. - The 2026-07 incident — IPv6 egress to the Scaleway S3 endpoint was blocked; WALs 015/016/017 never archived; every prd-par01 base backup was unrecoverable. This alert was added specifically to catch that class of failure.