> **See also:** [ROADMAP.md](../ROADMAP.md)

## v1.1.0 — PostgreSQL 17 Support

> **Release Theme**
> This release adds PostgreSQL 17 as a supported target alongside
> PostgreSQL 18. PGlite is built on PostgreSQL 17, so this is a hard
> prerequisite for the PGlite proof of concept (v0.29.0). The pgrx 0.17.x
> framework already supports PG 17 — the work is enabling the feature flag,
> adapting version-sensitive code paths, expanding the CI matrix, and
> validating the full test suite against a PG 17 instance.

### Cargo & Build System

| Item | Description | Effort | Ref |
|------|-------------|--------|-----|
| PG17-1 | **Add `pg17` feature to `Cargo.toml`.** Define `pg17 = ["pgrx/pg17", "pgrx-tests/pg17"]` feature. Keep `default = ["pg18"]`. | 1h | — |
| PG17-2 | **Broaden `#[cfg]` guards in `src/dag.rs`.** Three `#[cfg(feature = "pg18")]` blocks must become `#[cfg(any(feature = "pg17", feature = "pg18"))]`. | 1–2h | — |
| PG17-3 | **Guard `NodeTag` numeric assertions.** `src/dvm/parser/mod.rs` asserts specific `NodeTag` integer values (e.g., `T_GroupingSet = 107`) that shift between PG versions. Gate behind `#[cfg(feature = "pg18")]` or use per-version value tables. | 2–4h | — |
| PG17-4 | **Audit `pg_sys::*` API surface.** Verify that every `pg_sys` call compiles and behaves correctly on PG 17 bindings. Focus on catalog struct field names, WAL decoder types, and any PG 18-only additions. | 4–8h | — |

### CI & Infrastructure

| Item | Description | Effort | Ref |
|------|-------------|--------|-----|
| PG17-5 | **CI matrix expansion.** Add PG 17 build + unit test job to `ci.yml`. Use `postgres:17` Docker image for integration and light E2E tests. | 4–8h | — |
| PG17-6 | **`justfile` parameterisation.** Add `pg17` variants for build, test, and package recipes (e.g., `just build-pg17`, `just test-e2e-pg17`). | 2–4h | — |
| PG17-7 | **`tests/Dockerfile.e2e` PG version parameter.** Accept a build arg for the base PostgreSQL image version so the same Dockerfile works for PG 17 and PG 18. | 2–4h | — |
| PG17-8 | **Scripts parameterisation.** Update `run_unit_tests.sh`, `run_light_e2e_tests.sh`, `run_e2e_tests.sh` to accept a PG version argument instead of hardcoding `pg18`. | 2–4h | — |

### Testing & Validation

| Item | Description | Effort | Ref |
|------|-------------|--------|-----|
| PG17-9 | **Full E2E suite against PG 17.** Run the complete E2E test suite against a PG 17 instance. Fix any parser or catalog incompatibilities that surface. | 1–2d | — |
| PG17-10 | **TPC-H validation on PG 17.** Run TPC-H benchmark queries on PG 17 to verify differential refresh correctness for complex queries. | 4–8h | — |
| PG17-11 | **Upgrade path test.** Verify `ALTER EXTENSION pg_trickle UPDATE` from 0.25.0 to 0.26.0 works on both PG 17 and PG 18. | 2–4h | — |

### Documentation

| Item | Description | Effort | Ref |
|------|-------------|--------|-----|
| PG17-12 | **Update docs and README.** Change "PostgreSQL 18 extension" to "PostgreSQL 17/18 extension" in `README.md`, `INSTALL.md`, `src/lib.rs` doc comments, and `ARCHITECTURE.md`. | 1–2h | — |
| PG17-13 | **Docker Hub image variants.** Publish images tagged with both PG versions (e.g., `:0.25.0-pg17`, `:0.25.0-pg18`). | 2–4h | — |

### PostgreSQL 18/19 Feature Integration

Low-hanging PostgreSQL feature opportunities identified in [plans/sql/PLAN_POSTGRESQL_FEATURES.md](plans/sql/PLAN_POSTGRESQL_FEATURES.md). These are quick wins with minimal code effort or documentation-only updates.

#### Documentation-Only Items (Zero Code)

| Item | Description | Effort | Ref |
|------|-------------|--------|-----|
| PGFEAT-1 | **Document `extension_control_path` in INSTALL.md.** Add `extension_control_path` GUC as an alternative to the default `sharedir` for non-standard installations (NixOS, custom Kubernetes init containers). | 30min | [PLAN_POSTGRESQL_FEATURES.md](plans/sql/PLAN_POSTGRESQL_FEATURES.md#low-extension_control_path) |
| PGFEAT-2 | **Update CONFIGURATION.md for idle replication slot timeout.** Document PG 18's `idle_replication_slot_timeout` GUC and its interaction with pg_trickle's WAL-mode CDC. Add health check note. | 1h | [PLAN_POSTGRESQL_FEATURES.md](plans/sql/PLAN_POSTGRESQL_FEATURES.md#low-idle-replication-slot-timeout) |
| PGFEAT-3 | **Verify & document logical replication of generated columns.** Confirm WAL decoder correctly handles stored generated columns in change buffer schemas. Add E2E test and documentation note. | 1–2h | [PLAN_POSTGRESQL_FEATURES.md](plans/sql/PLAN_POSTGRESQL_FEATURES.md#low-logical-replication-of-generated-columns) |

#### Code Changes (Low Effort)

| Item | Description | Effort | Ref |
|------|-------------|--------|-----|
| PGFEAT-4 | **Add NOT ENFORCED constraints to storage tables.** Add `NOT ENFORCED` foreign keys and check constraints during `CREATE EXTENSION` and stream table creation to document relationships (FK to source) and invariants (`__pgt_count > 0`) without runtime overhead. | 2–3h | [PLAN_POSTGRESQL_FEATURES.md](plans/sql/PLAN_POSTGRESQL_FEATURES.md#high-not-enforced-constraints) |
| PGFEAT-5 | **AIO subsystem benchmarking.** Re-run E2E refresh benchmarks on PG 18 with `io_method = io_uring` (Linux) enabled. Document recommended settings in CONFIGURATION.md and BENCHMARK.md. | 3–4h | [PLAN_POSTGRESQL_FEATURES.md](plans/sql/PLAN_POSTGRESQL_FEATURES.md#high-asynchronous-io-subsystem) |

#### Additional PostgreSQL 18 Features

| Item | Description | Effort | Ref |
|------|-------------|--------|-----|
| PGFEAT-6 | **PG_MODULE_MAGIC_EXT support.** Adopt `PG_MODULE_MAGIC_EXT` in `lib.rs` to expose pg_trickle's version via the standard PostgreSQL interface. Enables third-party monitoring tools (pgwatch, Datadog, cloud providers) to discover pg_trickle version. Requires pgrx 0.17.x support first (verify). | 1h | [PLAN_POSTGRESQL_FEATURES.md](plans/sql/PLAN_POSTGRESQL_FEATURES.md#medium-pg_module_magic_ext) |
| PGFEAT-7 | **Skip Scan index optimization evaluation.** Evaluate multi-column B-tree indexes on change buffer tables `(source_relid, change_lsn)` to enable skip scan for multi-source delta lookups. Run `EXPLAIN` benchmarks on existing delta queries to quantify benefit. Create indexes if beneficial. | 2–3h | [PLAN_POSTGRESQL_FEATURES.md](plans/sql/PLAN_POSTGRESQL_FEATURES.md#medium-skip-scan-for-b-tree-indexes) |
| PGFEAT-8 | **OLD/NEW in MERGE RETURNING integration.** Refactor `build_merge_sql()` in `src/refresh.rs` to use `MERGE ... RETURNING OLD.*, NEW.*` for capturing displaced rows in a single round-trip. Eliminates separate pre-refresh snapshots for ST-to-ST change buffers. Improves full-refresh delta computation performance. | 4–6h | [PLAN_POSTGRESQL_FEATURES.md](plans/sql/PLAN_POSTGRESQL_FEATURES.md#high-oldnew-in-returning-for-merge) |
| PGFEAT-9 | **Virtual generated columns CDC support.** Verify and test that pg_trickle's trigger-based CDC correctly excludes virtual generated columns from change buffer schemas. Update `resolve_referenced_column_defs()` function if needed. Add E2E tests with virtual generated column sources and storage tables. | 4–6h | [PLAN_POSTGRESQL_FEATURES.md](plans/sql/PLAN_POSTGRESQL_FEATURES.md#high-virtual-generated-columns) |

> **PostgreSQL feature integration subtotal: ~4–5 hours** (PGFEAT-1 through PGFEAT-5) **+ ~10–18 hours** (PGFEAT-6 through PGFEAT-9, optional but recommended)

> **v1.1.0 total: ~2–4 days** (PG 17 support) **+ ~14–23 hours** (PostgreSQL feature integration, all items)

**Exit criteria:**
- [ ] PG17-1: `cargo build --features pg17 --no-default-features` compiles cleanly
- [ ] PG17-2/PG17-3: `cargo clippy --features pg17 --no-default-features` passes with zero warnings
- [ ] PG17-4: No `pg_sys` compile errors on PG 17 bindings
- [ ] PG17-5: CI runs unit + integration + light E2E tests on PG 17
- [ ] PG17-9: Full E2E suite passes on PG 17 with zero failures
- [ ] PG17-10: TPC-H differential refresh matches full refresh on PG 17
- [ ] PG17-11: Extension upgrade path works on both PG 17 and PG 18
- [ ] PG17-12: Documentation reflects PG 17/18 dual support
- [ ] PGFEAT-1: INSTALL.md documents `extension_control_path` alternative
- [ ] PGFEAT-2: CONFIGURATION.md documents `idle_replication_slot_timeout` interaction
- [ ] PGFEAT-3: WAL decoder tested with stored generated columns; E2E test passes
- [ ] PGFEAT-4: Storage tables have NOT ENFORCED FK and CHECK constraints; no runtime overhead
- [ ] PGFEAT-5: E2E refresh benchmarks run with `io_method = io_uring`; CONFIGURATION.md updated with recommended settings
- [ ] PGFEAT-6: `PG_MODULE_MAGIC_EXT` integrated (once pgrx supports it); version discoverable via `pg_get_loaded_modules()`
- [ ] PGFEAT-7: Skip scan index optimization evaluated; benchmarks quantify benefit; indexes created if beneficial
- [ ] PGFEAT-8: `MERGE ... RETURNING OLD.*, NEW.*` integrated in `build_merge_sql()`; ST-to-ST change buffer performance improved
- [ ] PGFEAT-9: Virtual generated columns correctly excluded from CDC change buffer schemas; E2E tests pass with virtual column sources
- [ ] Extension upgrade path tested (`1.0.0 → 1.1.0`)
- [ ] `just check-version-sync` passes

---

