Software

PostgreSQL 19 breaking changes to check before upgrading

By · Tue Sep 29 2026 · 6 min read · 0 views

View as a Web Story

Software#database#postgresql 19#pg_upgrade#postgres upgrade#breaking changes

PostgreSQL 19 upgrade checklist covering removed features and pg_upgrade blockers

PostgreSQL 19 is not released yet, but its list of breaking changes is already fixed enough to check your cluster against. The PostgreSQL project released Beta 4 on September 24, 2026. It says the release candidate should follow in early October, and that general availability may also land in October.

The official PostgreSQL 19 release notes list every incompatibility. This post turns that list into queries you can run today, and says who should wait.

Is PostgreSQL 19 released yet?

PostgreSQL 19 is the next major version of the PostgreSQL database, and it is still in beta as of September 29, 2026. The Beta 4 announcement says the next planned release is the release candidate in early October.

The beta removed several planned features to protect stability. Snowflake's engineering blog counts 53 reverted features, including SQL property graph queries, GROUP BY ALL and ALTER TABLE MERGE/SPLIT PARTITION, in its PostgreSQL 19 delay write-up. Snowflake calls PostgreSQL 18 the safe upgrade target today.

The release notes are dated as of September 14, and the final list can still change. Recheck it once the release candidate ships.

What breaks when you upgrade to PostgreSQL 19?

The release notes name more than a dozen compatibility changes. The table lists the ones most likely to hit a production cluster, each with what to check, and follows the Migration to Version 19 section.

Change in PostgreSQL 19 What to check
RADIUS authentication removed radius lines in pg_hba.conf
standard_conforming_strings forced on Old dumps made with it set to off
escape_string_warning removed The setting in postgresql.conf
MULE_INTERNAL encoding removed Databases created with that encoding
jit off by default Analytical workloads that relied on JIT
max_locks_per_transaction default 64 to 128 Any value you set by hand
MD5 password use now logs a warning Roles with md5 password hashes
json_array() with no rows returns an empty array Code that expected NULL
Read-only transactions reach postgres_fdw Writes through a read-only wrapper
Wait event BUFFERPIN renamed BUFFER Monitoring queries and dashboards

Methodology: we analyzed the Migration to Version 19 section of the release notes as of September 14, 2026, and paired every item with a check you can run. Fact-check: where a third-party guide disagrees, the table follows the release notes.

One third-party guide says all users must reset their passwords. The release notes say something narrower. PostgreSQL 19 issues a warning after a successful MD5 login, and you can turn that warning off with the md5_password_warnings server variable. MD5 passwords were already marked deprecated in PostgreSQL 18.

Which clusters will pg_upgrade refuse to upgrade?

pg_upgrade is the PostgreSQL tool that upgrades a cluster to a new major version without a full dump and restore. The pg_upgrade incompatibility entries list three conditions that make it stop.

  1. Line breaks in names. PostgreSQL 19 disallows carriage returns and line feeds in database, role and tablespace names, and pg_upgrade refuses clusters that use them. The notes say this was changed to avoid security problems.
  2. btree_gist indexes on inet or cidr. The default operator class for those types changes from btree_gist to GiST. The release notes call the old operator classes broken, because they can exclude rows that should be returned.
  3. The MULE_INTERNAL encoding. The encoding is removed, so databases using it must be dumped and restored under a different encoding.

What changes silently in PostgreSQL 19?

Some changes raise no error and only alter behaviour, according to the compatibility list in the release notes. For example, a reporting database can slow down after jit flips to off. These are the ones to test.

Advertisement

JIT is just-in-time compilation, which speeds up long analytical queries by compiling parts of them. PostgreSQL 19 turns it off by default, because the release notes say its cost-based triggering proved unreliable. Sites that run many large analytical queries must turn jit back on by hand.

The max_locks_per_transaction default rises from 64 to 128. The release notes explain that lock size allocation changed, so a value you set yourself effectively needs doubling to keep the same capacity.

Three smaller changes also matter:

  • json_array() returns an empty JSON array instead of NULL when its query returns no rows.
  • COPY FROM ... WHERE no longer accepts system columns.
  • pg_stat_subscription_stats renames sync_error_count to sync_table_error_count.

The release notes also change the default TOAST compression from pglz to lz4, under performance changes rather than incompatibilities. Values already stored keep their old compression, per Neon's TOAST note.

What should I run before upgrading to PostgreSQL 19?

Run these against every cluster you plan to move. Each returns no rows or an expected value when the cluster is clean.

grep -inE 'radius' pg_hba.conf
grep -in 'escape_string_warning' postgresql.conf
psql -c "SHOW jit;"
psql -c "SHOW max_locks_per_transaction;"
psql -c "SHOW standard_conforming_strings;"

Then run these SQL checks:

-- MD5 password hashes (run as a superuser)
SELECT rolname FROM pg_authid WHERE left(rolpassword, 3) = 'md5';

-- MULE_INTERNAL databases
SELECT datname FROM pg_database
WHERE pg_encoding_to_char(encoding) = 'MULE_INTERNAL';

-- Line breaks in database, role or tablespace names
SELECT 'database' AS kind, datname AS name FROM pg_database WHERE datname ~ '[\r\n]'
UNION ALL SELECT 'role', rolname FROM pg_roles WHERE rolname ~ '[\r\n]'
UNION ALL SELECT 'tablespace', spcname FROM pg_tablespace WHERE spcname ~ '[\r\n]';

-- btree_gist indexes on inet or cidr
SELECT i.indexrelid::regclass AS index_name
FROM pg_index i
WHERE EXISTS (
  SELECT 1 FROM pg_opclass o
  WHERE o.opcname IN ('gist_inet_ops', 'gist_cidr_ops')
    AND o.oid = ANY (i.indclass::oid[])
);

The gist_inet_ops and gist_cidr_ops names come from the Neon breaking changes guide, since the release notes name the type but not the operator classes. Test the query on a copy first.

Then work through the fixes in order:

  1. Replace any radius line in pg_hba.conf with another method, such as LDAP, GSSAPI, certificates or SCRAM.
  2. Delete escape_string_warning from postgresql.conf.
  3. Re-dump any old dump made with standard_conforming_strings = off, using PostgreSQL 19 tools.
  4. Drop any btree_gist inet or cidr index before the upgrade, and recreate it afterward on the new default operator class.
  5. Rename databases, roles or tablespaces that contain line breaks.
  6. Update dashboards that filter on the BUFFERPIN wait event.

Should I upgrade to PostgreSQL 19 or stay on 18?

Stay on your current version until 19 reaches general availability, unless your version is about to lose support. The PostgreSQL versioning policy gives the final release date of each version.

Version Current minor Final release Days from September 29
14 14.24 November 12, 2026 44
15 15.19 November 11, 2027 408
16 16.15 November 9, 2028 772
17 17.11 November 8, 2029 1,136
18 18.6 November 14, 2030 1,507

The pattern is clear. Only PostgreSQL 14 runs out before 19 has had time to settle. A team on 14 should move to 17 or 18 now and treat 19 as a later step, because a beta with 53 reverted features is not a place to land a production database.

Teams on 15 or newer have at least a year. Use that time to run the checks above on a copy of production, so the 19 upgrade is a scheduled task and not a surprise.

Advertisement

FAQ

When will PostgreSQL 19 be released?

The PostgreSQL project says the release candidate should arrive in early October 2026, and that general availability may also occur in October. Beta 4 shipped on September 24, 2026. No final date is published yet.

What is removed in PostgreSQL 19?

PostgreSQL 19 removes RADIUS authentication, the MULE_INTERNAL encoding and the `escape_string_warning` setting. It also forces `standard_conforming_strings` to always be on. The release notes call RADIUS over UDP unfixably insecure.

Will pg_upgrade work for my PostgreSQL 19 upgrade?

Usually, but it refuses three cases. Those are database, role or tablespace names containing line breaks, `btree_gist` indexes on `inet` or `cidr` columns, and MULE_INTERNAL databases. Run the check queries before you plan a maintenance window.

Do I have to reset all passwords for PostgreSQL 19?

No. PostgreSQL 19 logs a warning after a successful MD5 login, and you can silence it with `md5_password_warnings`. MD5 was already deprecated in PostgreSQL 18, so moving roles to SCRAM is still the sensible direction.

Comments

Loading…

Sign in to join the conversation.

Related posts

Java 27 short-term release compared with Java 25 LTS support dates

Java 27 is not LTS: should you leave Java 25?

Java 27 shipped on September 15, 2026, and it is not a long-term-support release. Oracle says it will provide updates to JDK 27 until March 2027, when Oracle JDK 28 supersedes it. The next

Tue Sep 29 2026 · 6 min read · 0 views

Software

Kubernetes 1.34 end-of-life timeline across EKS, AKS and GKE

Kubernetes 1.34 reaches end of life on October 27

Kubernetes 1.34 reaches end of life on October 27, 2026, according to the Kubernetes patch release schedule. That is 28 days away. After that date the Kubernetes project ships no more 1.34 patches.

Tue Sep 29 2026 · 6 min read · 0 views

Software