Upgrading the seed node and installing PGD
==========================================

In this phase, you will perform a major version upgrade of your Postgres
distribution on the seed node and prepare it for Postgres Distributed
(PGD).

Preparing the seed node for the upgrade
---------------------------------------

You must take the seed node offline to perform the major version
upgrade. We highly recommend to disable the logical subscription before
stopping the service, as subscription metadata must be manually
refreshed after the upgrade.

1. On the seed node, disable logical replication:

.. code:: sql

       ALTER SUBSCRIPTION migration_seed_sub DISABLE;

1. Stop the existing Postgres instance on seed node:

.. code:: bash

       su -u enterprisedb --command "pg_ctl stop"

1. Install the packages for the target version on the seed node. Ensure
   the old version remains installed, as ``pg_upgrade`` requires
   binaries from both versions to perform the transition. See
   `Installing EPAS <https://www.enterprisedb.com/docs/epas/latest/installing/>`_  , `Installing PGE <https://www.enterprisedb.com/docs/pge/latest/installing/>`_  , or :ref:`Installing Postgres <Installing Postgres>`  for details.

2. Adjust your ``${PATH}`` environment variable to point to the new
   binaries (e.g., ``/usr/edb/as17/bin/`` ) and verify the version:

.. code:: bash

       which pg_ctl

Performing the in-place upgrade
-------------------------------

Use the ``--link`` flag with ``pg_upgrade`` for an in-place upgrade that
uses hard links instead of copying data files. This significantly
reduces the required disk space and time, though it requires both the
old (``${OLD_PGDATA}`` ) and new (``${NEW_PGDATA}`` ) directories to
reside on the same filesystem.

1. On the seed node, prepare the new data directory:

.. code:: bash

       OLD_PGDATA = ${PGDATA}
       unset PGDATA
       mkdir ${NEW_PGDATA}
       chown enterprisedb: ${NEW_PGDATA}
       chmod 700 ${NEW_PGDATA}
       su enterprisedb -c "initdb -D ${NEW_PGDATA} -E utf-8"

1. On seed node, run ``pg_upgrade`` in check mode first:

.. code:: bash

       mkdir /tmp/pg_upgrade
       cd /tmp/pg_upgrade
       su postgres -c "pg_upgrade \
       --old-datadir ${OLD_PGDATA} \
       --new-datadir ${NEW_PGDATA} \
       --old-bindir /usr/edb/as14/bin/ \
       --new-bindir /usr/edb/as17/bin/ \
       --link \
       --check"

1. If the check returns a positive result, perform the actual upgrade by
   executing the same command without the ``--check`` flag:

.. code:: bash

       cd /tmp/pg_upgrade
       su postgres -c "pg_upgrade \
       --old-datadir ${OLD_PGDATA} \
       --new-datadir ${NEW_PGDATA} \
       --old-bindir /usr/edb/as14/bin/ \
       --new-bindir /usr/edb/as17/bin/ \
       --link"

1. Once completed, start the new version of your Postgres distribution:

.. code:: bash

       su -u enterprisedb --command "pg_ctl start"

Re-enabling the subscription
----------------------------

Major version upgrades do not carry over the internal table-mapping
information for subscriptions; specifically, the catalog table
``pg_subscription_rel`` will be empty. Enabling the subscription
immediately would cause the replication slot to be moved forward without
synchronizing table data, resulting in data loss.

To avoid this, you must “bogus-configure” the subscription to prevent it
from advancing the real slot while you refresh the table metadata. You
can safely ignore errors being reported in the seed node logs about the
slot not existing.

1. On the seed node, point to a bogus slot to safely refresh metadata:

.. code:: sql

       ALTER SUBSCRIPTION migration_seed_sub SET (slot_name = bogus);

1. Enable and refresh the publication:

.. code:: sql

       ALTER SUBSCRIPTION migration_seed_sub ENABLE;
       ALTER SUBSCRIPTION migration_seed_sub REFRESH PUBLICATION WITH (copy_data = false);
       ALTER SUBSCRIPTION migration_seed_sub DISABLE;

1. Verify that the table list in the subscription matches the
   configuration you obtained on :ref:`Enabling logical replication to the seed node <Enabling logical replication to the seed node>`  :

.. code:: sql

       SELECT n.nspname AS schemaname,
           c.relname AS tablename,
           sr.srsubstate AS state,
           s.subname AS subscription_name
       FROM pg_subscription_rel sr
       JOIN pg_class c ON sr.srrelid = c.oid
       JOIN pg_namespace n ON c.relnamespace = n.oid
       JOIN pg_subscription s ON sr.srsubid = s.oid
       WHERE s.subname = migration_seed_sub
       ORDER BY n.nspname, c.relname;

1. Revert the subscription to the correct slot and resume replication at
   the right LSN:

.. code:: sql

       ALTER SUBSCRIPTION migration_seed_sub
           SET (slot_name = migration_node_${SEED_NODE_NAME});
       ALTER SUBSCRIPTION migration_seed_sub ENABLE;

At this stage, the seed node is running the new Postgres version and
receiving logical updates from the source primary. Allow the system to
settle and ensure the seed node has fully caught up before moving to
initialize PGD.

Next step: :ref:`Initializing PGD <Initializing PGD>`  .
