# v0.59.0 — Performance & Observability > **Full details:** [v0.59.0.md-full.md](v0.59.0.md-full.md) ## What's New v0.59.0 closes the MEDIUM-severity performance and observability gaps identified in the v0.57.0 overall assessment ([plans/PLAN_OVERALL_ASSESSMENT_12.md](../plans/PLAN_OVERALL_ASSESSMENT_12.md)). It eliminates several hot-path allocations and SPI fan-outs, and adds the Prometheus metrics that SREs need to operate stream tables confidently in production. ### PERF-1: Batched Monitor Buffer-Growth Check (P-1) The health-check loop in `src/monitor/health.rs` previously issued one `SELECT count(*)` SPI call per CDC-enabled source table. On a cluster with 100 CDC sources at a 10 Hz monitor tick, this produced ~1 000 SPI round-trips per second. The check is now batched into a single SPI query using a `VALUES` lateral union, reducing the cost from O(N × ticks) to O(ticks). ### PERF-2: Query Hash Cached on StreamTableMeta (P-2) `defining_query_hash` is computed once at CREATE/ALTER time and stored in `pgtrickle.pgt_stream_tables`. The per-refresh hash computation (`DefaultHasher` over the full query string) is eliminated. The SQL upgrade script adds the new column and backfills it for all existing stream tables. ### PERF-3: Arc Merge Template Strings (P-3) The eight SQL template strings inside `CachedMergeTemplate` are now stored as `Arc`. Cache-hit clones become cheap atomic reference-count increments instead of multi-kilobyte `memcpy` operations. ### PERF-4: Single MERGE_TEMPLATE_CACHE Borrow per Refresh (P-4) `cached_non_monotonic` and `cached_is_deduplicated` are now extracted in a single `RefCell::borrow()` call, preventing the second borrow from distorting LRU ordering and halving the number of cache-lock acquisitions per refresh. ### PERF-5: WAL Decoder UPDATE Path Vec Pre-allocation (P-5) The WAL-decoder UPDATE handler now calls `Vec::with_capacity(num_columns)` before the column loop and uses `write!` into a single pre-allocated `String` for placeholder construction, eliminating the five separate `Vec` allocations (plus multiple `to_string()` calls) per UPDATE row. ### PERF-6: Frontier Borrow Instead of Clone (P-6) `has_stream_table_source_changes()` now borrows `st.frontier` via `as_ref().unwrap_or(&Frontier::EMPTY)` instead of cloning the entire `Frontier` struct (which contains a `HashMap` of upstream LSN entries) on every upstream-change probe. ### PERF-7: Diamond Detection — Lazy Intersection (P-7) The pair-wise branch-ancestor intersection in `detect_diamonds()` now uses a lazy `intersection()` iterator that short-circuits on the first shared node, avoiding the `collect()` into a temporary `Vec` for every branch pair. ### OBS-1: CDC Lag Percentile Metrics (O-1) Three new Prometheus gauges expose CDC-lag distribution across all live stream tables: - `pg_trickle_cdc_lag_p50_seconds` — median lag - `pg_trickle_cdc_lag_p95_seconds` — 95th percentile lag - `pg_trickle_cdc_lag_p99_seconds` — 99th percentile lag Percentiles are computed from a rolling 15-minute sample window stored in shared memory and updated on every frontier advance. ### OBS-2: Parallel Worker Queue-Depth and Idle-Time Metrics (O-2) Two new Prometheus counters expose parallel worker utilisation: - `pg_trickle_parallel_queue_depth` — number of refresh jobs waiting for a worker - `pg_trickle_worker_idle_time_seconds_total` — cumulative time workers have spent waiting for work ### OBS-3: WAL Decoder Pending-Record Metric (O-3) `pg_trickle_wal_decoder_pending_records` exposes the number of logical replication records buffered but not yet written to the CDC change buffer. A persistent non-zero value indicates the decoder is falling behind and allows operators to alert before the replication slot runs out of WAL. ### OBS-4: Refresh-Mode Ratio Metric per Stream Table (O-4) Two new Prometheus counters track mode selection per stream table: - `pg_trickle_refresh_mode_total{mode="differential",pgt_id="…"}` — count of DIFFERENTIAL refresh cycles - `pg_trickle_refresh_mode_total{mode="full",pgt_id="…"}` — count of FULL refresh cycles These counters let operators verify that the adaptive cost model is keeping queries on the differential hot path and detect unexpected fallback patterns. ### OBS-5: Background Worker application_name Tagging (O-5) All background worker connections now call `SET application_name = 'pg_trickle_'` immediately after connecting. Scheduler, dispatcher, pool worker, and WAL decoder processes are now individually identifiable in `pg_stat_activity`, `pg_stat_bgwriter`, and `pg_locks`. ### OBS-6: Backup & Restore Documentation (O-6) `INSTALL.md` gains a new "Backup & Restore" section documenting the required `pg_dump` flags to include both the `pgtrickle` catalog schema and the `pgtrickle_changes` change-buffer schema. The section also covers post-restore validation using `pgtrickle.health_check()`.