Repository navigation
Releases
v1.8.0
v1.8.0 - 2026-11-11
Features
- Added OpenTelemetry as a pluggable analysis input: OTLP/HTTP trace spans can now be turned into deploy events with the new
otlpsource type, every detected regression can be exported as an OTLP log record, and the Prometheus sample source gained bearer-token auth, failure metrics and a validated worked Collector pipeline. (#182) - Separated the two data floors that
--min-executionsused to blur: the new--min-samples(default 10) counts latency observations per window, while--min-executionsnow counts real executions (default 100, was 10 samples), so rarely-called queries report InsufficientData until enough calls back the verdict. (#210) - Detected regressions now expose the raw Welch's t-test
pValuein the PerformanceRegression status (and a P-Value kubectl column), the dashboard API, alerts and OTLP export;confidenceScorestays as1 - pValueand is documented as a significance score, not the probability that the regression is real. (#211) - Added a browser playground to the docs that runs the real detection engine, compiled to WebAssembly, against a real PostgreSQL with
pg_stat_statements(PGlite): pick a scenario or write your own schema, workload and deploy, and see which queries are flagged, with no Postgres or Kubernetes to install. (#212) - Added opt-in false-discovery-rate control across queries (
--multiple-testing=bh|by) and an autocorrelation adjustment for Welch's t-test (--adjust-autocorrelation), as operator flags andPostgresWatchfields, so a pass over hundreds of noisy queries reports fewer chance detections; both are off by default and change nothing until enabled. (#219) - Added a five-minute lab (
examples/lab, documented on the "Try it in five minutes" page): threekubectl applycommands start a throwaway Postgres, a demo app and the radar in any Kubernetes cluster, ship a deploy whose migration drops an index, and show the radar detecting it, naming the deploy and reporting theIndex Scan -> Seq Scanplan change. It needs no database, ArgoCD, Slack or Helm of your own. (#229)
Fixes
- Fixed regressions being hidden by the cumulative average: the collector now measures each query from the change in calls and total time between scrapes, and recognises counter resets (including
stats_sinceon PostgreSQL 17+) so they no longer look like latency changes. (#209) - Fixed the plan-diff summary on a detected regression, which with the default
--min-samplesalmost never had a "before" plan and could read "root node type unchanged" after an index drop. The plan history now records one entry per distinct plan instead of one per scrape, so the plan from before the change is still there when detection fires. (#228)
v1.7.0
v1.7.0 - 2026-11-09
Features
- Added GET /api/v1/queries/{queryId}/samples for per-query sample history, enabled CORS on every dashboard API route, and changed queryId to a JSON string across the API so large pg_stat_statements ids no longer get silently rounded by JavaScript clients. (#162)
- Added
internal/telemetry/promsource, an opt-incorrelation.SampleSourcebacked by PromQL queries against a Prometheus HTTP API, for fleets that already run an OpenTelemetry Collector and would rather not run a secondpg_stat_statementsscraper against the same database. Not yet wired intocmd/manager; that's a follow-up PR. (#163) - Wired
internal/telemetry/promsourceinto the CRD-drivencmd/managerpath:PostgresWatch.spec.sampleSource.type: prometheusnow selects it as an opt-in alternative tointernal/collector.Collector, skippingdsn/dsnSecretRefentirely and rejectingcapturePlans: true(which needs a direct database connection this mode doesn't have) with a clear error instead of ignoring it. (#164) - Completed multi-cluster (fleet) support: a new reconciler proactively health-checks every registered cluster's kubeconfig,
PostgresWatch.spec.cnpgClusterRefvalidates a remote CloudNativePGClusterbefore a watch starts, and both are wired into the Helm chart and a new real two-kind-cluster end-to-end CI workflow. (#174) - Added a
backport release-X.Ypull request label: a maintainer can say exactly which supported tool versions a merged fix should also reach, and the fix is automatically cherry-picked onto eachrelease-X.Ymaintenance branch (opening a draft pull request for manual resolution on a conflict). Every pull request's branch is also now deleted automatically once it closes. (#176)
Fixes
- Fixed a self-feedback loop where the collector's own EXPLAIN plan-capture queries were recorded as new pg_stat_statements entries, which could grow into repeated capture failures or a false-positive regression of their own; these ghost entries are now excluded from both sampling and plan capture, with a new metric tracking how often it happens. (#161)
- Fixed PostgreSQL collection for unprivileged roles by skipping statistics rows with hidden query IDs, allowing their own queries to be scraped in single-cluster and remote fleet deployments. (#175)
v1.6.0
v1.6.0 - 2026-09-23
Features
- Added a read-only dashboard HTTP API (
GET /api/v1/regressions,/deploys,/queries,/watches), enabled with the new--dashboard-addrflag on the operator and manager, so the observability dashboard can read regression, deploy, query-sample, and watch data without inventing any metric the correlation engine doesn't already compute. (#159)
v1.5.0
v1.5.0 - 2026-08-16
Features
-
Alerting destinations can now be governed by a configurable
destinationPolicy.
Three modes are available:permissive(default): unchanged behaviour — any URL that passes the built-in SSRF blocklist is accepted. Fully backward-compatible.allowlist: the webhook URL's host must appear in--alerting-allowed-destinations. Reconciliation fails fast with a clear error when the host is outside the list. Intended for multi-tenant clusters where only a pre-approved set of receivers should be reachable.relay-only: per-watchspec.alerting.urlis ignored entirely; all alerts are forwarded to the fixed relay endpoint in--alerting-destination-policy-relay-url. The manager and operator both fail at startup if the relay URL is missing, surfacing misconfiguration before any watch is reconciled.
The policy is configured via two new flags shared by both the
managerand the standaloneoperator:--alerting-destination-policy=<permissive|allowlist|relay-only> --alerting-destination-policy-relay-url=<url> # required for relay-onlyPostgresWatch.spec.alerting.destinationPolicymirrors these values at the per-watch level and is honoured when no manager-level policy is set.See Alerting: destination policies and Security model for configuration examples and deployment guidance.
(#136)
-
Introduces the
PostgresRadarClusterCRD so administrators can pre-register remote clusters;PostgresWatchnow references them by name viaspec.remoteClusterRef, eliminating the confused-deputy risk of direct kubeconfig Secret access. (#138) -
Operators can now cryptographically verify every released artifact. All five container images and the Helm OCI chart are signed with Cosign keyless signing; each image carries an attached SPDX SBOM attestation. A new
docs/supply-chain.mdpage documents the trust model and step-by-stepcosign verifycommands. A companionscripts/verify-release.shautomates the checks. (#139) -
Completed the final security-roadmap deployment gaps by adding Helm controls for alerting destination policies and ServiceAccount token automount, plus release provenance attestations for published images and the Helm OCI chart. (#141)
v1.4.0
v1.4.0 - 2026-08-15
Features
- Added a sample Kyverno
ClusterPolicyfor restricting who can apply thepg-regression-radar.io/allow-postgreswatch-accessconsent label, and documented it as a recommended hardening control for multi-tenant clusters. (#122)
Fixes
- Replaced bare
http.ListenAndServein the collector metrics server with a timeout-aware*http.Server(settingReadHeaderTimeout,ReadTimeout,WriteTimeout, andIdleTimeout) and added graceful shutdown on context cancellation, resolving gosec G114 / CWE-676. Also added the same timeout fields tohttpRunnablein the operator manager, resolving the companion G112 / CWE-400 finding. (#108) CaptureGenericPlanandCapturePlannow accept aNormalizedQueryTextvalue instead of a barestring, enforcing at compile time that only text originating frompg_stat_statementsreaches theEXPLAINstatement. This closes the SQL-injection path (CWE-089 / CodeQLgo/sql-injectionalert #3) reported againstinternal/planner/genericplan.go. (#109)- The Helm chart Secret template now includes the
pg-regression-radar.io/allow-postgreswatch-access: "true"consent label, fixing out-of-the-box breakage where the controller rejected the chart-created Secret on every reconciliation loop. (#110) - Added the
pg-regression-radar.io/allow-postgreswatch-access: "true"consent label to the Helm chart's Secret template so a defaultmode: managerinstall works without manual post-install patching. (#115) - Added an opt-in alerting destination allowlist for operator and manager mode, and clarified that the built-in webhook URL validation is only a best-effort SSRF mitigation that should be paired with stricter network or admission controls in multi-tenant clusters. (#119)
- BuildNotifier now treats an empty webhook URL as alerting disabled, returning a no-op notifier and rejecting empty URLs during direct webhook validation. (#125)
v1.3.1
v1.3.1 - 2026-08-15
Fixes
- PostgresWatch now requires Secrets referenced by dsnSecretRef or remoteClusterSecretRef to carry an explicit consent label before the manager will read them, closing a confused-deputy path. Remote kubeconfigs using exec-based or auth-provider credential plugins, or setting proxy-url, are now rejected outright instead of being trusted. (#94)
- Alert webhook URLs are now validated against SSRF-prone destinations, deploy-event HTTP servers enforce request-size and timeout limits, the standalone ingester can gate /events behind the same webhook secret, the Helm chart runs pods with hardened non-root security defaults, and the Kubernetes-native watcher no longer drops events when multiple DeploySources target the same workload. (#96)
v1.3.0
v1.3.0 - 2026-08-14
Features
- Added Prometheus counters for detected regressions and webhook notification successes or failures, so operators can alert on broken delivery paths and chart alerting reliability from
/metrics. (#87)
Fixes
- Webhook notifications now drain response bodies before closing them so Go can reuse keep-alive HTTP connections between alerts. (#89)
- Malformed PostgreSQL DSNs that look like redacted or broken connection URIs are now rejected at operator startup with a clear parse error instead of silently falling back to localhost until scrape time. (#90)
- Collector scrapes now cap
pg_stat_statementsquery text at the configured--max-query-text-lenbudget instead of always asking PostgreSQL for up to 500 characters per row. (#91) - Manager startup failures that prevent controller informers from reaching the Kubernetes API now best-effort mark existing PostgresWatch and DeploySource resources with a non-empty degraded status instead of leaving them blank. (#92)
- Periodic regressions now carry the configured namespace, so alerts, queries, and Kubernetes resources stay scoped to the same namespace as the PostgresWatch or operator configuration. (#93)
v1.2.0
v1.2.0 - 2026-08-14
Features
- Alerting now supports more than Slack:
--alert-format/spec.alerting.formatselects betweenslack(default, unchanged),teams(Microsoft Teams Incoming Webhook),pagerduty(Events API v2, opens/updates an incident), orcustom(a user-supplied Gotext/template, for any destination that isn't one of the built-in three).slackWebhookUrl/--slack-urlkeep working exactly as before. See Alerting for the full field/flag reference and the custom template's available fields. (#71) - Regression detection no longer requires a tracked deploy.
--periodic-detection/spec.periodicDetection.enabledruns the same E-divisive/Welch's-t-test analysis on a rolling schedule, per query, independent of anyDeployEvent— catching regressions with no deploy behind them (autovacuum lag, index bloat, stale planner stats, organic growth) that were previously invisible to this tool. A re-arm state machine suppresses repeat alerts for an ongoing episode until the query recovers. Deploy-triggered detection is unaffected either way; the two paths run side by side. See Periodic Detection for configuration and the false-positive caveat, and ADR-0001 for the design rationale. (#73)
v1.1.0
v1.1.0 - 2026-08-13
Features
- Make deploy-event retry analysis observable: the operator and manager now log when a deploy event is registered for retry and when its analysis window elapses, and expose a
pg_regression_radar_pending_deploy_eventsgauge, so an operator can tell "still waiting for data" apart from a silent failure and confirm memory stays bounded over long uptimes. (#65) - Add a native Kubernetes watch deploy source: setting
sourceType: kuberneteson aDeploySourceCR watches a Deployment or StatefulSet directly and emits a deploy event once its rollout completes, so clusters with no ArgoCD, Argo Rollouts, or Flux installed can still be correlated against — no webhook required. (#66) - Add opt-in Argo Rollouts auto-abort: setting
autoAbort.enabledon aPostgresWatchnow aborts the Argo Rollouts canary behind a sufficiently confident detected regression automatically, instead of only alerting and waiting for a human to act, with its own confidence threshold and RBAC gate, and the outcome recorded on the resultingPerformanceRegression. (#67)
v1.0.2
v1.0.2 - 2026-08-13
Fixes
- Fix regression detection silently missing real regressions: both
operatorandmanagerused to analyse a deploy event exactly once, immediately on arrival, well before enough post-deploy data could exist — now analysis retries every poll tick until the deploy's analysis window closes, deduplicating notifications so a detected regression is still only ever reported once. (#64)