Databases7 min read

PostgreSQL end of life: plan your major upgrade

PostgreSQL ships one major version per year and patches each one for five years. Once that window closes, the database keeps running exactly as it did the day before, simply without fixes: on a VPS, nothing warns you. This guide explains how to read your version, what the end of support actually changes, and how to plan the upgrade without losing data.

One major version per year, five years of fixes

PostgreSQL ships a major version roughly once a year and maintains it for five years. After that, a final minor release comes out and the branch reaches end of life, always on the November minor release: PostgreSQL 13 stopped on 13 November 2025, and PostgreSQL 14 will stop on 12 November 2026. The branches still followed run from 14 to 18; 18 has been available since 25 September 2025, and 19 is announced for September 2026.

What the end of support actually changes

  • No more fixes — a vulnerability published after end of life will not be patched on your branch: the code stays as it is, indefinitely.
  • Extensions fall behindPostGIS, pgvector or TimescaleDB stop publishing packages for a dead branch, and the next requirement becomes a blocker.
  • Distribution packages disappear — no more updates through apt, and reinstalling the VPS will not necessarily bring back the same version.
  • Compliance notices it — an audit, a customer questionnaire or an insurance contract will flag an unmaintained component long before an incident happens.
  • Clients and drivers move on — recent tooling (psql, pg_dump, application drivers) assumes supported server versions; the gap eventually produces errors that are hard to read.

Finding out which version you actually run

The server is authoritative, not your deployment file. Connect and run SELECT version();, or SHOW server_version; for the bare value. On Debian and Ubuntu, pg_lsclusters lists every cluster with its version, its port and its state, including the ones forgotten during an earlier upgrade. In containers, the image tag is misleading: replacing postgres:16 with a newer tag does not convert the files already written in the volume.

Planning the major upgrade

01

Back up, then verify the backup

Export roles and global settings with pg_dumpall --globals-only, then each database with pg_dump -Fc. A backup only counts once it has been restored: replay it into a throwaway cluster and compare row counts on your main tables.

02

Choose between logical export and in-place conversion

pg_dump followed by pg_restore rebuilds everything in a fresh cluster: simple, reversible, but the downtime follows the volume. pg_upgrade converts the catalog of the existing cluster in minutes, provided you install the binaries of both versions side by side.

03

Rehearse the migration on a copy

Do not test on the machine serving traffic. Spin up a second VPS, restore the backup there, then run pg_upgrade --check: it validates compatibility without writing anything and lists the manual adjustments to expect. Time the operation: that measurement sets your window.

04

Cut over with writes stopped

Stop the application, then shut the server down cleanly. Run the conversion or the restore, restart on the new cluster, and let traffic back in after a first check. Choose the mode knowingly: --link and --swap speed up the cutover but leave the old cluster unusable.

05

Check after the cutover

Confirm the version with SELECT version();, update your extensions with ALTER EXTENSION ... UPDATE, then regenerate optimizer statistics with vacuumdb --all --analyze-in-stages. Only delete the old data directory after several days of real production use, using the script pg_upgrade points to.

06

Run a full backup cycle again

Your archives from before the cutover describe a cluster that no longer exists. Take a full backup on the new version and test its restore: our guide on encrypted backups with restic covers rotation and integrity checking. On a Cloud VPS, that schedule stays yours.

pg_dump/restore or pg_upgrade: how to decide

Criterionpg_dump / pg_restorepg_upgrade
PrincipleLogical export, then reimport into a fresh clusterConversion of the existing cluster's catalog
DowntimeProportional to the data volumeA few minutes, largely volume-independent in `--link` or `--swap` mode
Disk spaceRoom for the archive, then for both clusters`--link` does not copy the files, but requires the same file system
RollbackThe old cluster stays intact and the archive stays replayableAfter `--link` or `--swap`, the old cluster can no longer be started
Pre-flight checkFailure shows up late, during the import`pg_upgrade --check` validates before any write
Optimizer statisticsFully rebuilt after the importMostly carried over since PostgreSQL 18, rebuilt before that
Parallelism`pg_dump -j` and `pg_restore -j``--jobs` to process several databases in parallel
Typical use caseModest volumes, a change of machine, a reorganizationLarge volumes, in-place upgrades, a short window

The real check is the restore

A branch at end of life raises no alert, and neither does a backup that has never been restored. Before the cutover, list the archive with pg_restore --list, restore it fully on a separate machine, and compare row counts on your sensitive tables. Then write your branch's end-of-life date into the calendar that already holds your renewals: a silent deadline becomes a planned task.

An up-to-date database on a VPS you control

On a ServOrbit Cloud VPS, you choose the major PostgreSQL version, you upgrade when your window allows it and you keep the old cluster while you validate. Full root access, no version imposed on you.

Need help?

Browse our help center and FAQ, or write to our team — support in French, English and Arabic.