Drop PostgreSQL 16 support from main, making PG17 the minimum supported version (supported: 17, 18, and 19 in flight).
Follows the same shape as the PG15 drop: #8351 / #8372 (62a919066) plus the follow-up cleanup #8377 (529b303b6).
Plan — two PRs
PR 1 — build, source, and CI drop
Build / version plumbing
configure.ac + configure: != '16' -a != '17' -a != '18' → != '17' -a != '18'
src/include/pg_version_constants.h: delete #define PG_VERSION_16
.gitattributes: drop the ruleutils_16.c -citus-style line
Source
- Delete
src/backend/distributed/deparser/ruleutils_16.c (~9.2k lines)
- Rename
metadata/pg_get_object_address_16_17_18.c → pg_get_object_address_17_18.c
src/include/pg_version_compat.h: collapse the #elif PG_VERSION_NUM >= PG_VERSION_17 branch to #else; unconditionalize the large #if PG_VERSION_NUM >= PG_VERSION_17 block and delete its legacy #else half
- 21
.c files / ~60 guard sites: #if PG_VERSION_NUM >= PG_VERSION_17 becomes unconditional, #if PG_VERSION_NUM < PG_VERSION_17 blocks are removed. Heaviest: multi_explain.c (31 sites), recursive_planning.c (3), and 2 each in role.c, merge_planner.c, shardsplit_decoder.c, columnar_tableam.c, citus_depended_object.c
recursive_planning.c L512–538: the "Distributed queries with outer joins and pseudoconstant quals are not supported in PG16" error path becomes dead code and is removed
Deprecated GUC (see "GUC handling" below)
citus.enable_outer_joins_with_pseudoconstant_quals_pre_pg17 stays defined but inert, gains a deprecation warning via a check hook, and gets a rewritten description
CI / dev env
.github/workflows/build_and_test.yml: remove pg16_version, its 5 matrix entries, the citus-upgrade PG16 entry, and pg-upgrade pairs 16→17 / 16→18; set upgrade_pg_versions: "17.10-18.4"
.github/workflows/flaky_test_debugging.yml: pg16_version → pg17_version
.devcontainer/Dockerfile: drop the pg16 build stage and its COPY
PR 2 — test output and helper cleanup
src/test/regress/bin/normalize.sed: remove the block explicitly flagged # can be removed when dropping PG16 support (L293–306), plus the CHECK-constraint-parens and CREATE MATERIALIZED VIEW DEBUG rules
- Remove
server_version_ge_17 gates from grant_on_table_propagation, multi_alter_table_add_constraints, multi_mx_create_table, multi_mx_hide_shard_names, multi_schema_support, pg15, pg17, pg17_json and regenerate the .out files
pg17.sql: drop the three SET/RESET citus.enable_outer_joins_with_pseudoconstant_quals_pre_pg17 pairs (L223/231, 247/253, 273/281). They are PG16-era scaffolding that is already a no-op on PG17+, and leaving them would make every run emit the new deprecation warning.
- Delete now-unreachable alternative outputs:
columnar_chunk_filtering_0.out, subquery_in_where_0.out, pg17_0.out, multi_mx_hide_shard_names_0.out, and friends
- Retire helpers
explain_with_pg16_subplan_format and initplan_references_to_pg17, plus the %3$s -- >= pg16 options argument in multi_test_helpers.sql and columnar_test_helpers.sql
- Fold
create_drop_database_propagation_pg16.sql into the main test file and update multi_1_schedule
- Delete
src/test/regress/{sql,expected}/pg16.* and remove test: pg16 from multi_1_create_citus_schedule
- Opportunistic, while in the same files: delete the stale
create_drop_database_propagation_pg15.{sql,out} left behind by the PG15 drop, and fix the ruleutils_17.c L12 reference to ruleutils_16.c plus the incorrect #endif comment at ruleutils_18.c L10359
Explicitly out of scope
No SQL migration. This drop touches no files under src/backend/distributed/sql/. The PG15 drop (62a919066) set that precedent, and keeping it migration-free keeps the risk profile low.
Two related items were split out rather than bundled:
GUC handling
citus.enable_outer_joins_with_pseudoconstant_quals_pre_pg17 is not removed in 15.0. Removing it outright would make existing postgresql.conf / ALTER SYSTEM / ALTER DATABASE ... SET entries fail on startup. Instead it is left defined but inert, and anyone who still sets it gets told it is going away.
Implemented with a check hook, matching the existing WarnIfDeprecatedExecutorUsed / NoticeIfSubqueryPushdownEnabled pattern in shared_library_init.c:
/*
* WarnIfDeprecatedPseudoconstantQualsGucIsSet emits a deprecation warning when
* citus.enable_outer_joins_with_pseudoconstant_quals_pre_pg17 is set explicitly.
* The GUC only ever applied to PG16, which Citus no longer supports.
*/
static bool
WarnIfDeprecatedPseudoconstantQualsGucIsSet(bool *newval, void **extra,
GucSource source)
{
if (source != PGC_S_DEFAULT)
{
ereport(WARNING, (errcode(ERRCODE_WARNING_DEPRECATED_FEATURE),
errmsg("citus.enable_outer_joins_with_pseudoconstant_"
"quals_pre_pg17 has no effect and is deprecated"),
errdetail("This setting only applied to PostgreSQL 16, "
"which Citus no longer supports."),
errhint("Remove it from your configuration. It will be "
"removed in a future Citus release.")));
}
return true;
}
Behaviour notes:
source != PGC_S_DEFAULT means it fires for SET, ALTER SYSTEM, ALTER DATABASE/ROLE ... SET, and postgresql.conf — i.e. any environment where a customer has actually set it — but never for the built-in default, so a clean install is silent.
- It fires regardless of whether the value is
on or off, because either way the entry should be removed.
RESET / SET ... TO DEFAULT restores reset_val without re-invoking the check hook, so it does not double-warn. Worth confirming during implementation.
- Set in
postgresql.conf, this logs once per backend start. That is intentional nagging for a setting nobody should still have.
The description is rewritten so \dconfig-style introspection also reflects the state:
gettext_noop("This setting has no effect and is deprecated."),
gettext_noop("It only applied to PostgreSQL 16, which Citus no longer "
"supports. The setting is retained so existing configurations "
"keep loading, and will be removed in a future Citus release."),
Actual removal of the GUC, its backing variable EnableOuterJoinsWithPseudoconstantQualsPrePG17, and this hook is tracked in #8751 for 15.1.
Cross-repo impact
Required, blocking — citusdata/the-process
Sister PR needed, merged before PR 1 so the rebuilt CI images and new image_suffix are available (the PG15 sister PR citusdata/the-process#178 merged 3 days ahead).
circleci/images/PG_VERSIONS: remove PG16=16.14
circleci/images/Makefile: remove CITUS_UPGRADE_VERSIONS_16=v12.1.14
No change now — citusdata/packaging
The dockerfiles/*-pg16 build environments are still required by release-13.x (PG15/16/17) and release-12.1 (PG14/15/16). At Citus 15.0 release time, add 15.0: postgres_versions: [ 17, 18 ] to postgres-matrix.yml.
No change now — citusdata/docker
postgres-16/Dockerfile on master images released Citus 14.1.0, which still supports PG16. Retire once PG16 images are no longer published.
No change now — citusdata/tools
packaging_automation/publish_docker.py carries a postgres_16 enum entry and templates/docker/postgres-16/postgres-16.tmpl.dockerfile. Coupled to the docker repo; retire together.
No change — citusdata/test-automation
No PG16 references found.
Drop PostgreSQL 16 support from
main, making PG17 the minimum supported version (supported: 17, 18, and 19 in flight).Follows the same shape as the PG15 drop: #8351 / #8372 (
62a919066) plus the follow-up cleanup #8377 (529b303b6).Plan — two PRs
PR 1 — build, source, and CI drop
Build / version plumbing
configure.ac+configure:!= '16' -a != '17' -a != '18'→!= '17' -a != '18'src/include/pg_version_constants.h: delete#define PG_VERSION_16.gitattributes: drop theruleutils_16.c -citus-stylelineSource
src/backend/distributed/deparser/ruleutils_16.c(~9.2k lines)metadata/pg_get_object_address_16_17_18.c→pg_get_object_address_17_18.csrc/include/pg_version_compat.h: collapse the#elif PG_VERSION_NUM >= PG_VERSION_17branch to#else; unconditionalize the large#if PG_VERSION_NUM >= PG_VERSION_17block and delete its legacy#elsehalf.cfiles / ~60 guard sites:#if PG_VERSION_NUM >= PG_VERSION_17becomes unconditional,#if PG_VERSION_NUM < PG_VERSION_17blocks are removed. Heaviest:multi_explain.c(31 sites),recursive_planning.c(3), and 2 each inrole.c,merge_planner.c,shardsplit_decoder.c,columnar_tableam.c,citus_depended_object.crecursive_planning.cL512–538: the "Distributed queries with outer joins and pseudoconstant quals are not supported in PG16" error path becomes dead code and is removedDeprecated GUC (see "GUC handling" below)
citus.enable_outer_joins_with_pseudoconstant_quals_pre_pg17stays defined but inert, gains a deprecation warning via a check hook, and gets a rewritten descriptionCI / dev env
.github/workflows/build_and_test.yml: removepg16_version, its 5 matrix entries, the citus-upgrade PG16 entry, and pg-upgrade pairs16→17/16→18; setupgrade_pg_versions: "17.10-18.4".github/workflows/flaky_test_debugging.yml:pg16_version→pg17_version.devcontainer/Dockerfile: drop thepg16build stage and itsCOPYPR 2 — test output and helper cleanup
src/test/regress/bin/normalize.sed: remove the block explicitly flagged# can be removed when dropping PG16 support(L293–306), plus the CHECK-constraint-parens and CREATE MATERIALIZED VIEW DEBUG rulesserver_version_ge_17gates fromgrant_on_table_propagation,multi_alter_table_add_constraints,multi_mx_create_table,multi_mx_hide_shard_names,multi_schema_support,pg15,pg17,pg17_jsonand regenerate the.outfilespg17.sql: drop the threeSET/RESET citus.enable_outer_joins_with_pseudoconstant_quals_pre_pg17pairs (L223/231, 247/253, 273/281). They are PG16-era scaffolding that is already a no-op on PG17+, and leaving them would make every run emit the new deprecation warning.columnar_chunk_filtering_0.out,subquery_in_where_0.out,pg17_0.out,multi_mx_hide_shard_names_0.out, and friendsexplain_with_pg16_subplan_formatandinitplan_references_to_pg17, plus the%3$s -- >= pg16 optionsargument inmulti_test_helpers.sqlandcolumnar_test_helpers.sqlcreate_drop_database_propagation_pg16.sqlinto the main test file and updatemulti_1_schedulesrc/test/regress/{sql,expected}/pg16.*and removetest: pg16frommulti_1_create_citus_schedulecreate_drop_database_propagation_pg15.{sql,out}left behind by the PG15 drop, and fix theruleutils_17.cL12 reference toruleutils_16.cplus the incorrect#endifcomment atruleutils_18.cL10359Explicitly out of scope
No SQL migration. This drop touches no files under
src/backend/distributed/sql/. The PG15 drop (62a919066) set that precedent, and keeping it migration-free keeps the risk profile low.Two related items were split out rather than bundled:
citus_prepare_pg_upgrade/citus_finish_pg_upgrade. Already unreachable today, and removing them requires versioned UDF snapshots plus migration-script edits.test-citus-upgradeis missing a PG18 entry. Pre-existing gap; adding coverage for a different PG version is unrelated to removing one.GUC handling
citus.enable_outer_joins_with_pseudoconstant_quals_pre_pg17is not removed in 15.0. Removing it outright would make existingpostgresql.conf/ALTER SYSTEM/ALTER DATABASE ... SETentries fail on startup. Instead it is left defined but inert, and anyone who still sets it gets told it is going away.Implemented with a check hook, matching the existing
WarnIfDeprecatedExecutorUsed/NoticeIfSubqueryPushdownEnabledpattern inshared_library_init.c:Behaviour notes:
source != PGC_S_DEFAULTmeans it fires forSET,ALTER SYSTEM,ALTER DATABASE/ROLE ... SET, andpostgresql.conf— i.e. any environment where a customer has actually set it — but never for the built-in default, so a clean install is silent.onoroff, because either way the entry should be removed.RESET/SET ... TO DEFAULTrestoresreset_valwithout re-invoking the check hook, so it does not double-warn. Worth confirming during implementation.postgresql.conf, this logs once per backend start. That is intentional nagging for a setting nobody should still have.The description is rewritten so
\dconfig-style introspection also reflects the state:Actual removal of the GUC, its backing variable
EnableOuterJoinsWithPseudoconstantQualsPrePG17, and this hook is tracked in #8751 for 15.1.Cross-repo impact
Required, blocking —
citusdata/the-processSister PR needed, merged before PR 1 so the rebuilt CI images and new
image_suffixare available (the PG15 sister PR citusdata/the-process#178 merged 3 days ahead).circleci/images/PG_VERSIONS: removePG16=16.14circleci/images/Makefile: removeCITUS_UPGRADE_VERSIONS_16=v12.1.14No change now —
citusdata/packagingThe
dockerfiles/*-pg16build environments are still required byrelease-13.x(PG15/16/17) andrelease-12.1(PG14/15/16). At Citus 15.0 release time, add15.0: postgres_versions: [ 17, 18 ]topostgres-matrix.yml.No change now —
citusdata/dockerpostgres-16/Dockerfileonmasterimages released Citus 14.1.0, which still supports PG16. Retire once PG16 images are no longer published.No change now —
citusdata/toolspackaging_automation/publish_docker.pycarries apostgres_16enum entry andtemplates/docker/postgres-16/postgres-16.tmpl.dockerfile. Coupled to the docker repo; retire together.No change —
citusdata/test-automationNo PG16 references found.