A database upgrade is more than an image-tag change. Your application, extensions, access rules and recovery procedure all have to work on the destination. A separate test instance gives you somewhere to discover those problems while the current service continues running.
The examples below use PostgreSQL 18 client tools and a deliberately separate target database. They are a rehearsal for one application database, with a simplified ownership model. They do not switch live traffic or reproduce every cluster-wide setting.
What PostgreSQL 14 end of life means
The database does not stop accepting connections on its support deadline. The problem is continuing to rely on software that no longer receives community maintenance. A working application and a supported database are different checks.
Find the running version
Ask the database itself. A package listing or a local command-line client can describe a different installation.
Prove recovery
Restore a protected copy into an isolated target and run the application against it before reserving a maintenance window.
Plan the final writes
Decide how writes will stop or synchronise, who authorises cutover and when a simple rollback stops being possible.
On the date of this article, PostgreSQL 18 is a stable supported release; PostgreSQL 19 is still listed as development. Choose a supported version that your application and required extensions actually support. Do not turn an urgent maintenance job into an untested application migration.
1. Inventory databases, extensions and clients
Connect with an authorised account and run these SQL queries on the source database:
SHOW server_version;
SHOW server_version_num;
SELECT datname,
pg_size_pretty(pg_database_size(oid)) AS database_size
FROM pg_database
WHERE datistemplate = false
ORDER BY pg_database_size(oid) DESC;
SELECT extname, extversion
FROM pg_extension
ORDER BY extname;
The extension query covers the current database, so repeat it for each application database. Record database owners, application roles, tablespaces, scheduled jobs, connection pools and any replicas. Keep configuration files and the application's connection settings alongside the inventory.
List every writer, including background workers, Discord bots, automation jobs and scheduled tasks. Pausing a website alone does not stop a queue worker from changing the same database. A useful rehearsal has a written list of what must be quiet at cutover.
Check the application's own database support matrix. Extensions such as vector search or geospatial modules may require a particular image or package. Their files must be available on the target, and extension installation privileges vary.
2. Choose a migration method that fits the downtime
PostgreSQL documents three main major-upgrade approaches. You can skip intermediate major versions, but review their migration notes for changes that affect your application.
| Method | Useful when | Plan for |
|---|---|---|
| Logical dump and restore | A measured restore fits the maintenance window | Export, data loading, indexes and application checks |
| pg_upgrade | You control both installations and need a faster cluster upgrade | Compatible binaries, extension libraries and a tested recovery path |
| Logical replication | A larger migration needs a shorter final write pause | Schema, sequence handling, lag and final synchronisation |
pg_upgrade has a compatibility-check mode. Its link mode can reduce copying, but starting the upgraded cluster prevents ordinary reuse of the old linked cluster. Treat that as a recovery design decision, not a free speed switch.
Logical replication has limits: schema changes and sequence state need separate handling, and large objects are not replicated. It can reduce downtime, but it does not remove the cutover work. This article follows the easier-to-inspect dump-and-restore route.
3. Prepare an isolated target and protect the backup
Provision the destination with its own data directory and storage. Keep the test application away from real email, webhooks, payments and production queues: a copied database may contain enough configuration to trigger real actions.
For a PostgreSQL 18 destination, install the PostgreSQL 18 versions of pg_dump, pg_restore, psql and createdb on the machine running the examples. Verify the selected binaries:
pg_dump --version
pg_dumpall --version
pg_restore --version
psql --version
createdb --version
Use the destination version's dump tools to read the older server, as the pg_dump documentation describes. Replace the example hostnames and users below. Connect over a trusted private route or correctly configured database TLS; do not expose PostgreSQL publicly just to run a migration.
The shell examples assume Bash on Linux. Set restrictive permissions before creating database exports:
umask 077
mkdir -p ~/pg14-rehearsal
cd ~/pg14-rehearsal
Use password prompts for an interactive run. For repeated jobs, PostgreSQL supports a password file; on Unix it must exclude group and public access, typically mode 0600. Keep credentials out of connection URLs pasted into shell history.
4. Export the application database and review globals
Create a custom-format archive of a source database called appdb. The account must be allowed to export all required objects and data:
pg_dump \
--host=old-db.example.internal --port=5432 \
--username=app_owner --dbname=appdb \
--format=custom --quote-all-identifiers \
--file=appdb-pg14.dump
pg_restore --list appdb-pg14.dump
Check the export command's exit status and warnings before continuing. Writing through --file avoids sending a binary archive through a shell text-redirection path. The list command confirms that the archive table of contents is readable; a successful restore is the next test.
A single database dump does not contain every cluster object. With an appropriately privileged source administrator, export globals separately:
pg_dumpall \
--host=old-db.example.internal --port=5432 \
--username=source_admin --globals-only \
--file=cluster-globals.sql
The globals export includes roles and tablespaces and may contain sensitive authentication material. Protect it and review it before deciding what belongs on the destination. Do not blindly run it against a staging server with existing roles or different filesystem paths.
A live dump is consistent, but later source writes are absent from that copy. That is fine for an initial rehearsal. It is not a final migration of a database that keeps changing.
5. Restore into a new test database
First prepare a dedicated target role named app_rehearsal, its authentication and the required extension packages. Have the target administrator create an empty database from template0. Verify the source's intended encoding, locale and collation provider, then select suitable matching target settings; defaults are not automatically equivalent.
createdb \
--host=new-db.example.internal --port=5432 \
--username=target_admin \
--owner=app_rehearsal --template=template0 \
app_rehearsal
The createdb options also let you set encoding and locale explicitly. The command above assumes the target defaults have already been checked. Administrators should install any extension that the rehearsal role cannot create.
Restore the archive using the rehearsal role:
pg_restore \
--host=new-db.example.internal --port=5432 \
--username=app_rehearsal --dbname=app_rehearsal \
--exit-on-error --no-owner --no-privileges \
--no-tablespaces \
appdb-pg14.dump
These restore options deliberately omit original ownership, access grants and tablespace placement. Ordinary restored objects use the restoring role. This helps test a simple application copy; it does not prove that production permissions or storage placement have been preserved.
Role references inside policies and other definitions may still need matching roles. If the source uses row-level security or several owners, rehearse those identities and grants separately. Stop on an error and investigate it. --exit-on-error does not undo objects already restored; retry against a fresh empty test database.
Collect planner statistics after restoration using an authorised target account:
psql \
--host=new-db.example.internal --port=5432 \
--username=app_rehearsal --dbname=app_rehearsal \
--set=ON_ERROR_STOP=1 --command='ANALYZE;'
ANALYZE gives the query planner statistics about the restored data. Run representative queries and compare behaviour, not just whether the database accepts a connection.
Docker: the PostgreSQL 18 volume change matters
For the official PostgreSQL image, version 18 changes the default layout: the volume mount moves to /var/lib/postgresql, with PGDATA at /var/lib/postgresql/18/docker. Older official-image examples usually mount /var/lib/postgresql/data.
A new layout does not convert an old database. Create a separate destination volume, confirm where it writes data, and use the migration method you rehearsed. Keep the original service and data identifiable until recovery and retention requirements are met.
Application-specific images may package required extensions or prescribe their own migration sequence. Follow that application's documentation before replacing an image with plain postgres. Avoid docker compose down -v during migration: it can remove the volumes you still need. Our Compose update guide explains the distinction between routine container replacement and data migration.
6. Test the application before scheduling cutover
- Data: compare important record counts and known recent records from the same rehearsal point. Check uploaded files or external storage that the database references.
- Behaviour: test login, reads, writes, search, reports, background jobs and a new record that exercises sequences.
- Access: verify each application's privileges, connection-pool settings and administrative access with the intended production roles.
- Performance: run normal queries and monitor CPU, memory, disk space and database activity. Record restore and index-build duration.
- Recovery: restore the protected backup again somewhere separate. Write down who can do it and how long it takes.
If an OS or base-image change also changes locale libraries, review collation behaviour and the version-specific maintenance requirements. Do not dismiss a collation warning merely because a login test passes.
Reserve capacity for source data, the archive, destination data and index creation. Check actual free space and measured timings; an upgrade estimate based only on database file size can miss the work that follows data loading.
7. Use a written cutover and rollback checklist
Before the switch
Confirm the backup and rehearsal results. Pause every writer, take the final export or complete the tested sync, and verify the destination.
At the switch
Update application connections and restart the relevant pools and workers. Run read and write checks, then monitor errors and queues.
After new writes
Keep one authoritative database. A return to the old server now requires a plan for changes written to the new one.
Define an abort point before reopening writes. Keep the old instance isolated from application traffic, preserve the migration records and start the destination's normal backup schedule. A successful migration is not permission to remove every recovery copy immediately.
Revisit ongoing PostgreSQL backups after the upgrade. Choose retention and recovery methods around how much data you can afford to lose; a rehearsal export alone is not a complete backup policy.
Where HYEHOST fits into the upgrade
A separate Cloud VPS gives you an independent destination for rehearsal or cutover in Wolverhampton, Ashburn or Auckland. Choose the region around application traffic and check database latency from the app, particularly if they will run on different servers.
Use VDS hosting when dedicated CPU and RAM suit the workload, and keep protected database exports off the database host with a Storage Box. Our rclone backup guide covers an encrypted SFTP workflow. Hosting capacity supports the plan; application compatibility and a verified restore remain part of your migration work.
PostgreSQL 14 upgrade FAQ
When does PostgreSQL 14 reach end of life?
The PostgreSQL community lists 12 November 2026 as PostgreSQL 14's final release date. After community support ends, PostgreSQL 14 no longer receives community bug or security fixes.
Can I upgrade PostgreSQL 14 directly to 18?
A direct major-version upgrade is possible without installing every intermediate version. Check application and extension support, read the intervening migration notes and rehearse the chosen method first.
Can I upgrade a Docker database by changing postgres:14 to postgres:18?
No. Changing the image tag does not convert the database files. Use a supported migration method and a separate target data volume; PostgreSQL 18's official image also changes the default data-directory layout.
Does pg_dump include users and roles?
A database dump does not include cluster-wide roles and tablespaces. Export globals separately, protect that file and review how roles, ownership and permissions will be recreated.
Is pg_restore --list enough to test a backup?
No. It shows the archive's contents, but you must restore into an isolated database and test the application, data, permissions and recovery procedure.
Can I switch back to the old database after the upgrade?
Before accepting new writes, an unchanged source can be part of a rollback plan. Once applications write to the new database, switching back can lose those changes unless you reconcile them. Define that decision point before cutover.

