Move a cluster to a new Postgres major version, without changing your PGD version, using one of three approaches: full downtime, a rolling upgrade in place, or a rolling upgrade that replaces nodes one at a time.
Note
If you're also upgrading PGD to a new minor version at the same time, see Upgrading Postgres and PGD together instead.
Upgrading with full downtime
Choose this approach when a maintenance window is acceptable and finishing quickly matters more than staying online. See Choosing between a rolling and full-downtime upgrade for the trade-offs against the two rolling approaches described below.
Disconnect applications from the cluster, then on each node, run the same steps as upgrading with a rolling upgrade, in place below, except you can skip checking or switching the write leader and fencing or unfencing the node, since nothing is serving traffic during the upgrade. Once every node is upgraded, confirm each one is running the new Postgres version and healthy, then reconnect applications.
Upgrading with a rolling upgrade, in place
Plan your upgrade order across the cluster, one node at a time, upgrading each group's write leader last. Disconnect applications from the old Postgres cluster, or redirect them to another node in the PGD cluster.
Use the command-line utility pgd node upgrade to upgrade a node in place. It wraps the standard pg_upgrade, adding PGD-specific steps around it so replication slots and origins carry over correctly.
For each node, one at a time:
Install the new major version's PGD packages alongside the existing ones:
sudo apt install edb-pgd6-expanded-pg<postgres_version>
Package managers install each Postgres major version to its own path, so the old binaries are untouched.
Create a fresh, empty data directory for the new cluster using the new version's
initdb, matching the old cluster's checksum and locale settings. Leave this new cluster shut down.Copy the old cluster's
postgresql.confandpostgresql.auto.conf,pg_hba.conf, andconf.ddirectory (if present) into the new data directory, adjusting for any configuration parameters that changed between Postgres major versions.Check whether the node you're upgrading is the write leader for its group:
pgd group <group_name> show --summary
If it is, switch leadership to another node first, since
pgd node upgradedoesn't manage this switch for you:pgd group <group_name> set-leader <new_leader_node_name>
Fence the node so it can't become the write leader again while it's being upgraded:
pgd node <node_name> set-option route_fence true
Make sure the old cluster is running.
pgd node upgradestarts it if it's shut down.Run
pgd node upgradewith the--checkoption first to validate the upgrade without making changes:pgd node <node_name> upgrade --check \ --old-bindir <old_bindir> \ --new-bindir <new_bindir> \ --old-datadir <old_datadir> \ --new-datadir <new_datadir> \ --database <database_name> \ --username <install_user>
--old-bindirand--new-bindirare the old and new Postgres installation'sbindirectories.--old-datadirand--new-datadirare the old cluster's data directory and the empty new data directory you created earlier.--databaseis the PGD-enabled database name, and--usernameis the cluster's install user.--checkruns the PGD-specific validation andpg_upgrade --check, without modifying either cluster. See Modes of operation for what running with--checkvalidates.Run
pgd node upgradeagain without--checkto perform the upgrade, using the same options:pgd node <node_name> upgrade \ --old-bindir <old_bindir> \ --new-bindir <new_bindir> \ --old-datadir <old_datadir> \ --new-datadir <new_datadir> \ --database <database_name> \ --username <install_user>
Unfence the node:
pgd node <node_name> set-option route_fence false
Confirm the node is healthy and running the new Postgres version before moving on:
pgd nodes list --versionsMove to the next node in your planned upgrade order, upgrading write leaders last in each group.
For the full set of options and flags, see the pgd node upgrade command reference.
Example
Upgrade the node kaolin from Postgres 16 to Postgres 17:
pgd node kaolin upgrade \ --old-bindir /usr/lib/postgresql/16/bin \ --new-bindir /usr/lib/postgresql/17/bin \ --old-datadir /var/lib/postgresql/16/main \ --new-datadir /var/lib/postgresql/17/main \ --database bdrdb
See the command reference for more examples, including hard links, file cloning, and Transparent Data Encryption (TDE).
Upgrading with a rolling upgrade, by replacing nodes
Instead of upgrading a node in place, join a new node that already has the new Postgres version installed,
then drop one of the existing nodes running the old version. This approach avoids pg_upgrade entirely, at the cost
of a full data transfer to the new node.
Provision a new machine, or a new instance, with the new Postgres major version and the same PGD version as the rest of the cluster already installed.
Join the new node to the cluster using a logical join:
pgd node <node_name> setup --dsn "<new_node_dsn>" --cluster-dsn "<existing_node_dsn>" -D <pg_data>
Note
Don't use
bdr_init_physical, it requires the source and joining node to run the same Postgres major version, so it can't be used across a major version change.See the
pgd node setupcommand reference for the full set of options.Wait for the new node to catch up with the cluster before routing traffic to it.
Confirm the new node is healthy and running the new Postgres version:
pgd nodes list --versionsUpdate your application's connection configuration, or the Connection Manager, to include the new node.
Disconnect applications from the old node before parting it, or redirect them to another node in the PGD cluster.
Part the old node, then decommission it:
pgd node <node_name> part
Repeat for each remaining old node, one at a time, until the whole cluster is on the new version.
Note
While nodes are on mixed Postgres major versions, avoid using any feature or DDL syntax that's only available in the newer version, until every node has been replaced.