# v0.20.0 — Self-Monitoring (pg_trickle Monitors Itself)

> **Full technical details:** [v0.20.0.md-full.md](v0.20.0.md-full.md)

**Status: ✅ Released** | **Scope: Large** (~6 weeks)

> pg_trickle uses its own stream table technology to maintain reactive
> analytics about its own behaviour — detecting anomalies, tuning thresholds
> automatically, and demonstrating incremental view maintenance on a
> non-trivial real workload.

---

## What problem does this solve?

Operators running pg_trickle in production needed answers to questions like:
"Is my differential refresh consistently faster than a full refresh?" and
"Is my change buffer growing unexpectedly?" Answering these required running
diagnostic queries that scanned potentially large history tables on demand.

The self-monitoring release turns these diagnostics into continuously-maintained
stream tables — pg_trickle watches its own behaviour incrementally, the same
way it watches your application data. Answers are always available
instantaneously, without re-scanning history.

---

## Five Self-Monitoring Stream Tables

`pgtrickle.setup_self_monitoring()` creates five stream tables that monitor
pg_trickle's own internal catalog and refresh history:

**`df_efficiency_rolling`** — Rolling averages of differential and full
refresh times per stream table. Replaces expensive full-scan calls to
`refresh_efficiency()` with a continuously-maintained result.

*In plain terms:* "How fast are my stream tables refreshing, on average over
the last hour?" — answered instantly.

**`df_anomaly_signals`** — Detects duration spikes (a refresh that took
3× longer than average), error bursts, and mode oscillation (rapid switching
between DIFFERENTIAL and FULL).

*In plain terms:* "Did anything unusual happen in the last refresh cycle?"

**`df_threshold_advice`** — Multi-cycle threshold recommendations for AUTO
mode. Rather than computing a recommendation from a single data point, this
analyses trends across many cycles and assigns a confidence level.

*In plain terms:* "Should I adjust the AUTO mode threshold for this stream
table?" — with a specific recommendation and confidence rating.

**`df_cdc_buffer_trends`** — Tracks how fast the change buffer is growing
for each source table. Alerts when the buffer is growing toward a size that
will cause a slow refresh.

*In plain terms:* "Is any source table accumulating changes faster than
pg_trickle can process them?"

**`df_scheduling_interference`** — Detects when multiple stream table
refreshes are competing with each other, causing latency spikes due to
contention.

*In plain terms:* "Are my stream tables interfering with each other's
refresh schedules?"

---

## Auto-Apply Threshold Tuning

The `pg_trickle.self_monitoring_auto_apply` configuration option (when set
to `threshold_only`) allows pg_trickle to automatically adjust the AUTO mode
cost threshold for each stream table based on the recommendations from
`df_threshold_advice`, when the confidence is HIGH and the change is
significant.

Changes are rate-limited (at most once per stream table per 10 minutes) and
recorded in the refresh history with the reason `initiated_by = 'SELF_MONITOR'`
for auditability.

*In plain terms:* pg_trickle can tune itself — finding the optimal balance
between differential and full refresh for your specific workload, automatically.

---

## Grafana Self-Monitoring Dashboard

A new Grafana dashboard in `monitoring/grafana/` visualises all five
self-monitoring stream tables with live panels:

- Refresh throughput timeline
- Anomaly heatmap by stream table
- Threshold calibration scatter plot
- CDC buffer growth sparklines
- Scheduling interference matrix

---

## dbt Integration

A new `pgtrickle_enable_monitoring` dbt post-hook macro calls
`setup_self_monitoring()` automatically after a successful `dbt run`,
so dbt users get self-monitoring activated as part of their normal workflow.

---

## Operational Helpers

- **`pgtrickle.recommend_refresh_mode(name)`** — returns an instant
  recommendation based on `df_threshold_advice`, rather than computing
  one on demand
- **`pgtrickle.explain_dag()`** — returns the full stream table dependency
  graph as a Mermaid diagram, with colour-coding for user vs self-monitoring
  tables
- **`pgtrickle.scheduler_overhead()`** — shows the fraction of scheduler
  time spent on self-monitoring tables vs user tables (target: < 1%)

---

## Scope

v0.20.0 demonstrates pg_trickle's own value proposition on itself — a
non-trivial incremental analytics workload maintained continuously with
negligible overhead. The five self-monitoring stream tables replace on-demand
diagnostic queries with always-current reactive analytics, and the auto-apply
feature closes the feedback loop from monitoring to optimisation.
