A PostgreSQL major version is the first part of the version number, such as 16 in 16.4. Unlike roughly quarterly minor releases, which fix bugs, security issues, and data-corruption problems without changing formats, a major release adds vetted features and may change internal system-table and data-file formats. Data directories are therefore not directly compatible across major versions, although they can be upgraded. section 7.6
Treating a major-version upgrade as unnecessary because a system “works fine” is a production risk. Latent bugs, changing workloads, and new vulnerabilities can invalidate apparent stability; avoiding major upgrades also leaves improvements unavailable. Major versions are typically supported for five years with patches and security updates, and the upgrade path is characterized as reliable. section 7.6
Plan a major-version upgrade around both storage compatibility and behavioral change:
- Do not expect a previous major version to read the new version’s system tables or data files directly; use an upgrade path instead. section 7.6
- Read every intervening major-release note when skipping versions, not only the notes for the destination release. section 10.1
- Test application behavior as well as upgrade mechanics, because feature performance and semantics can change in subtle corner cases. section 10.1
- Keep minor releases current while planning the next major release; minor updates address bugs, security, and corruption issues. section 7.6
A skipped-release interval change
An application adds 0.333 years to an expiry timestamp. Before PostgreSQL 15, the fractional interval was truncated to 15 months, producing April 1 from January 1; from PostgreSQL 15 onward it is rounded to 16 months, producing May 1. Upgrading from 13 to 16 without reading the 14-to-15 notes can make this look like an unexplained PostgreSQL 16 regression. The safer diagnosis is to compare behavior on both versions and trace the change through every intervening release note. section 10.1
postgres=# SELECT 1.333*12 as months, ('1.333 years'::interval) as months;
months | months
--------+---------------
15.996 | 1 year 3 mons
(1 row)
Compare interval parsing output across versions to expose the shift from 1 year 3 months to 1 year 4 months for the same fractional-year input. section 10.1
SQL-level backward compatibility is generally strong: SQL written for PostgreSQL 9.3 will usually work on PostgreSQL 17. That compatibility does not remove the need to review release notes and test workloads, because changed behavior may be valid yet still conflict with application assumptions. section 7.6 section 10.1

