Chat on WhatsApp
CR Guard
CloudRevol
Database

PostgreSQL Upgrade from Version 12 to Version 18

PostgreSQL Upgrade from Version 12 to Version 18
Updated: September 11, 2026 ยท 15 min read

Learn how to safely upgrade PostgreSQL from Version 12 to Version 18 on Ubuntu 24.04 LTS with step-by-step instructions and best practices.

Overview

This guide explains how to upgrade PostgreSQL from Version 12 to Version 18 on Ubuntu 24.04 LTS. We'll cover the complete upgrade process, including preparation, migration, verification, and post-upgrade cleanup.

Prerequisites

  • Server running PostgreSQL 12
  • Ubuntu 24.04 LTS (Noble)
  • Shell access with sudo privileges
  • A verified logical backup and preferably a VM/storage snapshot
  • Enough free disk space for a second copy of the PostgreSQL cluster
  • A maintenance window with application writes stopped
  • PostgreSQL 18-compatible packages for all external extensions
Important: Always back up your databases before performing any PostgreSQL upgrade. This guide uses pg_upgrade copy mode and intentionally avoids --link so the PostgreSQL 12 cluster remains independently available for rollback during validation.

Step 1: Verify PostgreSQL 12 and Ubuntu 24.04

Confirm the operating system, cluster name, production port, server version, and data directory before making any changes.

cat /etc/os-release
pg_lsclusters
sudo -u postgres psql -X -Atc "SHOW server_version;"
sudo -u postgres psql -X -Atc "SHOW port;"
sudo -u postgres psql -X -Atc "SHOW data_directory;"
This guide assumes cluster 12/main and the standard production port 5432. If your server uses a different cluster name or port, substitute your real values.

Step 2: Back Up and Inventory PostgreSQL 12

Check Disk Space

df -hT
sudo du -sh /var/lib/postgresql/12/main

Create and Verify a Logical Backup

sudo mkdir -p /root/pg12-to-pg18-backup
sudo chmod 700 /root/pg12-to-pg18-backup
sudo -u postgres /usr/lib/postgresql/12/bin/pg_dumpall --verbose | gzip -1 | sudo tee /root/pg12-to-pg18-backup/postgresql12-pg_dumpall.sql.gz > /dev/null
sudo gzip -t /root/pg12-to-pg18-backup/postgresql12-pg_dumpall.sql.gz

Also take a VM or storage snapshot if available. A successfulgzip -t exits without an error.

Check Extensions and Preloaded Libraries

sudo -u postgres psql -X -Atc "SELECT datname FROM pg_database WHERE datallowconn AND NOT datistemplate ORDER BY datname;" |
while read -r DB; do
  echo "===== DATABASE: $DB ====="
  sudo -u postgres psql -X -d "$DB" -c "SELECT extname, extversion FROM pg_extension ORDER BY extname;"
done
sudo -u postgres psql -X -c "SHOW shared_preload_libraries;"
dpkg -l | grep -E '^ii[[:space:]]+postgresql-12'
Extension requirement: Install PostgreSQL 18-compatible binaries for every external extension before the actual upgrade. This includes modules such as PostGIS, pgaudit, TimescaleDB, pglogical, or custom C extensions when present.

Step 3: Add the Official PostgreSQL PGDG Repository

Ubuntu 24.04 Noble is supported by the official PostgreSQL APT repository. Use the signed .sources configuration instead of the deprecated apt-key method.

sudo apt update
sudo apt install -y curl ca-certificates postgresql-common
sudo install -d /usr/share/postgresql-common/pgdg
sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
sudo tee /etc/apt/sources.list.d/pgdg.sources > /dev/null <<EOF
Types: deb deb-src
URIs: https://apt.postgresql.org/pub/repos/apt
Suites: noble-pgdg
Architectures: $(dpkg --print-architecture)
Components: main
Signed-By: /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc
EOF
sudo apt update
apt-cache policy postgresql-18

Step 4: Install PostgreSQL 18 Binaries

sudo apt install -y postgresql-18 postgresql-client-18
/usr/lib/postgresql/18/bin/postgres --version
pg_lsclusters

Installation normally creates a new empty 18/maincluster on another port. PostgreSQL 12 should still be the active production cluster at this point.

Install the PostgreSQL 18 versions of all extension packages found in Step 2 before continuing. Do not use--force-packages to bypass a missing extension package.

Step 5: Remove Only the New Empty PostgreSQL 18 Cluster

pg_lsclusters
Critical: Run the next command only after confirming that 18/main is the newly created empty cluster. Never drop the PostgreSQL 12 production cluster here.
sudo pg_dropcluster --stop 18 main
pg_lsclusters

Check Required Upgrade Packages

sudo pg_upgradecluster --check --method=upgrade -v 18 12 main

The pg_upgradecluster --check option checks whether the PostgreSQL 18 packages required by the old cluster are installed. If it reports a missing package, stop and install it before proceeding.

Step 6: Enter Maintenance Mode and Stop PostgreSQL 12

Stop application writes, workers, and scheduled jobs using your normal deployment procedure, then check for remaining sessions.

sudo -u postgres psql -X -c "SELECT pid, usename, datname, application_name, client_addr, state FROM pg_stat_activity WHERE pid <> pg_backend_pid() ORDER BY datname, usename;"
sudo -u postgres psql -X -c "CHECKPOINT;"
sudo pg_ctlcluster 12 main stop
pg_lsclusters

Step 7: Upgrade PostgreSQL 12 Directly to PostgreSQL 18

Use pg_upgrade copy mode. The old PostgreSQL 12 data files remain independent because this command does not use --link.

sudo pg_upgradecluster -v 18 --method=upgrade --jobs=4 --no-start 12 main

Do not interrupt this process. Upgrade duration depends on database size, storage performance, tablespaces, and available CPU resources.

Step 8: Verify the Upgraded Cluster Layout

pg_lsclusters

PostgreSQL 18 should now own the original production port. The old PostgreSQL 12 cluster remains stopped on an unused port for rollback. The exact unused port can differ from server to server.

Step 9: Start and Verify PostgreSQL 18

sudo pg_ctlcluster 18 main start
pg_lsclusters
pg_isready -h 127.0.0.1 -p 5432
sudo -u postgres psql -X -c "SELECT version();"
sudo -u postgres psql -X -c "\l+"

Check Collation Versions

sudo -u postgres psql -X -c "SELECT datname, datcollversion AS recorded_version, pg_database_collation_actual_version(oid) AS actual_version FROM pg_database WHERE datallowconn ORDER BY datname;"
If a collation version has changed, rebuild affected indexes or collation-dependent objects before refreshing the recorded collation version. Do not blindly silence a collation mismatch warning.

Check PostgreSQL 18 Logs

sudo tail -100 /var/log/postgresql/postgresql-18-main.log
sudo grep -iE 'PANIC|FATAL|ERROR|could not load|incompatible|collation' /var/log/postgresql/postgresql-18-main.log | tail -100

Step 10: Restore Application Traffic and Keep PostgreSQL 12 for Rollback

Test application connections and critical read/write paths before restoring full production traffic. Keep the old PostgreSQL 12 cluster until PostgreSQL 18 has been fully validated and your rollback window has ended.

sudo -u postgres psql -X -c "SELECT datname, numbackends, xact_commit, xact_rollback, deadlocks FROM pg_stat_database ORDER BY datname;"
Only after full validation: The following command permanently removes the old PostgreSQL 12 cluster. Do not run it during the initial validation period.
sudo pg_dropcluster --stop 12 main

Post-Upgrade Best Practices

PostgreSQL 18 pg_upgrade can preserve optimizer statistics, so a full analyze is not mandatory solely because of the major upgrade. A staged analyze is still useful as a conservative maintenance step, especially after index rebuilds or other post-upgrade changes.

sudo -u postgres /usr/lib/postgresql/18/bin/vacuumdb --all --analyze-in-stages --jobs=4
sudo tail -f /var/log/postgresql/postgresql-18-main.log

Frequently Asked Questions

Is it safe to upgrade PostgreSQL from version 12 to version 18 directly?

Yes. PostgreSQL pg_upgrade supports direct upgrades from version 9.2 and later to PostgreSQL 18, so intermediate major-version upgrades are not required. Always create and verify a backup first.

How long does a PostgreSQL upgrade take?

The duration depends on database size, server performance and storage speed. Small databases may take only a few minutes, while larger production databases can take longer.

Will my PostgreSQL data be deleted during the upgrade?

No. The upgrade process migrates existing database clusters to the newer version. However, backups should always be created before any major upgrade.

Can I rollback to PostgreSQL 12 after upgrading?

Yes, when you use copy mode and keep the old PostgreSQL 12 cluster. Rollback is simplest before PostgreSQL 18 receives new production writes. Do not remove PostgreSQL 12 until validation is complete.

What are the benefits of PostgreSQL 18?

PostgreSQL 18 adds asynchronous I/O improvements, skip-scan support for multicolumn B-tree indexes, UUIDv7 generation, OAuth authentication support, and pg_upgrade improvements including preservation of optimizer statistics.

Do I need to update applications after upgrading PostgreSQL?

Most applications continue to work without modification. However, you should test application compatibility, database drivers and ORM libraries before upgrading production systems.

How do I verify PostgreSQL 18 is running correctly?

After the upgrade, run SELECT version(); and verify that PostgreSQL 18 is displayed. You should also check application connectivity and database logs.

Should I run VACUUM ANALYZE after upgrading?

PostgreSQL 18 can preserve optimizer statistics during pg_upgrade, so a full analyze is not mandatory only because of the upgrade. It can still be useful after index rebuilds or as a conservative post-upgrade maintenance step.

Need Help?

If you need assistance with PostgreSQL upgrades, migrations, or managed database services, contact CloudRevol Support.

[email protected]