# v0.10.0 — DVM Hardening, PgBouncer Compatibility, and "No Surprises" UX

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

**Status: ✅ Released** | **Scope: Medium** (~3–4 weeks)

> Differential engine hardening for complex SQL patterns, certified
> compatibility with PgBouncer connection pooling, refresh pipeline
> optimisations, and user-experience improvements that prevent silent
> failures.

---

## What problem does this solve?

As more users deployed pg_trickle in production, a set of recurring friction
points emerged: certain complex queries produced unexpected differential
results, PgBouncer deployments required manual workarounds, and the system
would sometimes fall back to full refresh without telling users why. v0.10.0
addresses all three themes.

---

## Differential Engine Hardening

Further correctness improvements to the differential engine for patterns
encountered in production:

- **Multi-level GROUP BY** — nested aggregation (aggregate of an aggregate)
  now correctly propagates deltas through each level
- **Mixed JOIN types** — queries mixing INNER, LEFT, and RIGHT JOINs in the
  same query now handle the differential interaction between join types
  correctly
- **DISTINCT in subqueries** — DISTINCT applied inside a subquery rather than
  at the top level was incorrectly collapsed in some cases
- **Empty group handling** — when the last row of a group is deleted, the
  group row in the stream table is now correctly removed (rather than lingering
  with a zero aggregate)

---

## PgBouncer Compatibility

**PgBouncer** is one of the most widely used PostgreSQL connection poolers,
used in virtually every large-scale PostgreSQL deployment. Its
*transaction-pooling mode* — the most common and efficient mode — reuses
database connections across client transactions, which requires careful
management of session state.

v0.10.0 certifies pg_trickle's compatibility with PgBouncer transaction
pooling mode and documents the required configuration. The background worker
now correctly handles connection interruptions that occur when PgBouncer
recycles a connection, and the diagnostic functions include a dedicated
PgBouncer compatibility check.

*In plain terms:* if your PostgreSQL deployment uses PgBouncer (and many do),
pg_trickle now works reliably without requiring a separate dedicated connection
pool or special workarounds.

---

## Refresh Pipeline Optimisations

Several improvements to the refresh execution path:

- The change buffer read is now filtered by the range of changes that are
  actually relevant to the current refresh, reducing the amount of data
  processed
- The MERGE statement used to apply delta changes was reorganised for better
  PostgreSQL query plan selection
- The differential SQL generation was made ~20% faster through string buffer
  pre-allocation

---

## "No Surprises" User Experience

A theme across several small improvements — making pg_trickle transparent
about what it is doing:

- When AUTO mode decides to run a FULL refresh instead of DIFFERENTIAL, it
  now logs the reason (the delta was too large, the query shape changed, etc.)
- When a stream table is created with a query pattern that has known
  limitations, a `NOTICE` is printed during creation rather than on the first
  refresh failure
- `explain_st()` now shows the last fallback reason and the current AUTO
  mode cost estimate

---

## Scope

v0.10.0 is a production hardening release. The differential engine
correctness improvements fix real patterns encountered by users, PgBouncer
compatibility removes a major deployment barrier, and the UX improvements
make the system more transparent and predictable.
