Trusted Postgres Architect 23.45.0 release notes v23.45.0

Released: 21 September 2026

PGD-S is no longer accepted

PGD-S (PGD Essential) is no longer offered as a product. tpaexec configure --architecture PGD-S now fails immediately, as does reconfigure/provision/deploy against an existing cluster whose config.yml still specifies architecture: PGD-S. Use PGD-X for new PGD 6 deployments.

Potential restart of Postgres on first deploy

On clusters where max_wal_senders and max_replication_slots are set only under postgres_conf_settings (not directly as cluster_vars), upgrading to 23.45.0 may restart Postgres once, if TPA's recalculated value differs from the value previously written to conf.d/0001-tpa_restart.conf. Setting both variables directly as cluster_vars, in the same deploy as the upgrade, avoids this.

New features, enhancements, bug fixes, and other changes in Trusted Postgres Architect 23.45.0 include the following:

Highlights

  • Split sysctl management into separate vm and network groups, so a routine deploy no longer resets operator-tuned network settings
  • Added support for running the TPA controller on, and experimentally deploying to, Debian 13 (trixie)
  • PGD-S (PGD Essential) is no longer accepted by tpaexec configure; use PGD-X instead

Enhancements

Description
TPA now splits its sysctl management into separate vm and network task groups.

TPA used to write a single mixed set of sysctls into /etc/sysctl.conf, combining Postgres-specific kernel tuning (the vm.dirty_* family,vm.zone_reclaim_mode) with general-purpose network and connection tuning (net.core.somaxconn, net.ipv4.tcp_max_syn_backlog, and others). A routine tpaexec deploy could silently reset network values that an operator had raised on purpose to handle their workload, which has caused production incidents.

TPA now splits these settings into two task selectors. sysctl_vmcovers the Postgres-specific group and is applied by default; exclude it with excluded_tasks: [sysctl_vm] to manage those settings yourself.sysctl_net covers the network group and is opt-in only, via a newopt_in_tasks mechanism: tpaexec configure --platform aws opts the cluster in by default, while bare-metal and other platforms stay opted out unless sysctl_net is added to opt_in_tasks. The settings are written to /etc/sysctl.d/30-tpa.conf rather than /etc/sysctl.conf, so an operator's own file under /etc/sysctl.d/ with a higher numeric prefix (for example /etc/sysctl.d/90-local.conf) takes precedence through the standard Linux mechanism, without going throughconfig.yml.

opt_in_tasks is a new third task-selector list (alongsideincluded_tasks and excluded_tasks) for tasks that should run only when explicitly opted in. Unlike included_tasks, it does not engage whitelist semantics: naming a task in opt_in_tasks opts that task in without implicitly excluding any other tasks.

The historical network defaults have also been audited against current Linux kernel defaults. net.core.somaxconn, net.ipv4.tcp_syncookies, and net.ipv4.tcp_tw_reuse are no longer set by TPA, since the kernel defaults are now the values TPA wanted. net.ipv4.ip_local_port_rangehas been narrowed at the bottom end so it no longer overlaps the privileged-port range.

On the first redeploy under the new layout, TPA also removes any of its historical sysctl lines from /etc/sysctl.conf, so the two files don't end up shadowing each other.

TPA now supports running the controller on Debian 13.

The TPA controller can now be a system running Debian 13 ("trixie"), either from a source checkout (using the system Python 3.13 packages) or via apt-get install tpaexec, now that tpaexec packages are published for Debian 13.

TPA now supports experimental deployment to Debian 13 (trixie) nodes.

TPA can now deploy to nodes running Debian 13 ("trixie"). Suitable Docker images or AWS AMIs are selected on the docker or aws platforms, and bare instances running Debian 13 are detected correctly.

This feature is experimental: deployment depends on the availability of the various packages for Debian 13, so not all architectures or software options will work until packages are uploaded to upstream repositories.

Debian 12 remains the default Debian version, so existing clusters and any new cluster configured without an explicit --os-version are unaffected.

TPA now supports preserving ansible.log across deprovision instead of deleting it.

tpaexec deprovision always deleted the cluster directory'sansible.log along with other generated files. Settingpreserve_ansible_log: true at the top level of config.yml now preserves it instead: the current log is renamed to ansible.log.N, one more than the highest existing suffix, leaving earlier logs under their original names. This is useful when repeatedly provisioning and deprovisioning the same cluster directory during development. Default behavior is unchanged.

TPA now supports controlling the startup of the Postgres service when EFM is the failover manager.

A new variable, efm_autostart_db, controls whether the Postgres service starts automatically after EFM starts when EFM is used as the failover manager. It defaults to false; set it to true to have Postgres start automatically once EFM starts.

TPA now provides an Echo (Debian-based) execution environment variant for AAP 2.4.

A new echo execution-environment base is available undertpa-ee/aap24/echo/, built on reg.echohq.com/python:3.12-slim("Echo Linux", a Debian derivative). It's an alternative to the existing alpine variant for users who need an apt-based, glibc image. Build it the same way as the other variants: build.sh -b echo.

TPA now supports the pgaa extension.

The pgaa extension can now be installed by TPA when listed in the extensions list. pgaa requires pgfs as a prerequisite; TPA checks for the presence of pgfs when pgaa is listed, to avoid failing later in the deployment.

To check the list of supported platforms and Postgres versions, see https://www.enterprisedb.com/docs/pgaa/latest/overview/compatibility/.

TPA now repeats its deliberate warnings in a recap at the end of a run.

Warnings that TPA raises on purpose to draw the operator's attention were printed only inline as a run proceeded, where they could scroll out of sight during a long deploy. TPA's output now collects those deliberate warnings and repeats them in a consolidated block after the PLAY RECAP, so they are not missed. Warnings emitted by Ansible itself are left out of this recap, so it stays focused on the messages TPA chose to raise.

TPA now supports the pgfs extension.

The pgfs extension can now be installed by TPA when listed in theextra_postgres_extensions list.

To check the list of supported platforms and Postgres versions, see https://www.enterprisedb.com/docs/pg_extensions/pgfs/compatibility/.

TPA now supports EFM 5.4's primary.health.check.port property.

EFM 5.4 adds a new property, primary.health.check.port, that load balancers can use to locate the primary node in a cluster. When set, an EFM agent listens on that port for incoming HTTP requests: the primary agent responds with a 200 status code, and other agents respond with a 404.

TPA now supports setting this property in efm_conf_settings; it is ignored if set while deploying a version of EFM before 5.4.

Changes

Description
TPA now requires --pgd-proxy-routing to be specified when reconfiguring a BDR4 cluster to PGD5.

When reconfiguring a BDR4 cluster to PGD5, --pgd-proxy-routing must now be set to global or local. This is enforced consistently for--describe, --check, and a real run, so an omitted or invalid value is now reported immediately instead of only being caught partway through the process.

Bug Fixes

DescriptionAddresses
Fixed an issue whereby recalculating max_wal_senders/max_replication_slots could trigger an unnecessary Postgres restart.

TPA calculates its own defaults for max_replication_slots andmax_wal_senders on every deploy and writes them toconf.d/0001-tpa_restart.conf, even on clusters where these settings are actually governed by postgres_conf_settings (which takes priority over any other value). Because the calculation formula formax_replication_slots has changed across recent TPA versions (to account for PGD 5 Parallel Apply), upgrading TPA could change the value written to conf.d/0001-tpa_restart.conf and trigger a Postgres restart, even when the values actually in effect (frompostgres_conf_settings) never changed.

TPA now validates that max_wal_senders is at least as large asmax_replication_slots, failing deployment with an explanatory error instead of silently adjusting either value as before. A newskip_wal_senders_validation variable is available as a temporary escape hatch for clusters transitioning an existing, inconsistent configuration.

To avoid the restart described above, set max_replication_slots andmax_wal_senders directly as cluster_vars with the value you want in effect, rather than only under postgres_conf_settings.

See the warning at the top of these release notes: upgrading to this version may still restart Postgres once if these variables are only set under postgres_conf_settings.

65323
Fixed an issue whereby BDR/PGD clusters on Postgres 16 and later could suffer a permanent Raft consensus failure on first startup.

Postgres 16 added output_plugin_libraries, an allow-list GUC that rejects any output plugin not named in it (default: pgoutput, test_decoding). BDR/PGD's consensus worker uses the bdr library itself as an output plugin, so on any build where this GUC exists and doesn't already allow bdr, the consensus worker crashed at first startup. That happened during the cluster's very first boot, while Raft was still bootstrapping, permanently stranding that node with no Raft leader: every later bdr.create_node_group() call then failed with "could not establish consensus leader", and the deploy failed.

TPA now adds bdr to output_plugin_libraries before Postgres ever starts, on any build that supports the GUC, so the consensus worker never crashes in the first place.

TPA also now retries BDR node group creation on transient consensus errors, as a defensive measure independent of the above.

Fixed an issue whereby pgd-proxy could fail to connect to Postgres because libpq environment variables were not passed to its systemd service.

The pgd-proxy service is started by systemd, which does not pass a user's ambient environment through to spawned services. As a result,pgd-proxy could fail to connect to Postgres when it relied on libpq environment variables, such as PGPASSFILE, that were not present in the service's environment.

TPA now sets these variables directly in the pgd-proxy systemd unit file via a new pgd_proxy_service_environment variable, which defaults to:

pgd_proxy_service_environment: PGPASSFILE: '{{ pgd_proxy_home }}/.pgpass' PGSSLMODE: 'require'

Each entry is rendered as an Environment= line in the unit file. You can override the variable under cluster_vars or a pgd-proxy instance's vars to change or add environment variables; the value you supply replaces the default mapping in full rather than being merged entry by entry.

61496, 63632
Fixed an issue whereby every deploy logged a spurious Ansible warning that the raw module does not support the environment keyword.

The task that records the deploy in the log file inherited a play-level environment it never used. It is now given an empty environment, so the spurious warning no longer appears. This is purely cosmetic; deployment behavior is unchanged.

Fixed an issue whereby PEM server nodes were given a fixed node name instead of a generated one.

PEM server nodes created with --enable-pem were always given the fixed name pemserver, instead of a generated name consistent with the naming scheme used by the rest of the cluster. This also prevented them from receiving a generated hostname via --hostnames-from. PEM server nodes now receive a generated node name and hostname like other nodes in the cluster.

Fixed an issue whereby changes to the pgd-proxy systemd unit file were not applied on redeploy.

Changes to the pgd-proxy systemd unit file (for example, editingpgd_proxy_service_environment) were written to disk but did not take effect on the running service when re-running tpaexec deploy on an existing cluster: the role restarted the service without first runningsystemctl daemon-reload, so systemd kept using its cached unit, and a change confined to the unit file did not trigger a restart at all.

TPA now reloads systemd and restarts pgd-proxy whenever the unit file changes, so unit-file settings are applied on redeploy as expected.

Fixed an issue whereby efm_bind_by_hostname was silently reset during EFM switchover and upgrade health checks.

When a cluster was configured with --efm-bind-by-hostname, EFM switchover (tpaexec switchover, and the EFM switchover step used mid-upgrade by tpaexec upgrade) and the EFM health checks run aroundtpaexec upgrade/tpaexec upgrade-efm incorrectly used the node's IP address instead of its hostname to identify itself when querying efm cluster-status-json. Both task files unconditionally reloaded EFM's role defaults (including efm_bind_by_hostname: false) over the user-configured value, silently reverting the cluster to IP-based identification. As a result, tasks that look up a node by its EFM identity (efm set-priority, cluster-status polling, and the "node is part of allowed nodes" check) could fail on clusters configured with--efm-bind-by-hostname.

The role defaults are now only used as a fallback for variables that are not already defined, so a user-configured efm_bind_by_hostname(and efm_cluster_status_retries/efm_cluster_status_retry_delay, if overridden) is preserved.

Fixed an issue whereby the Patroni rewind user lacked the privileges pg_rewind needs.

The Patroni rewind user (patroni_rewind_user, default rewind) was created as a plain non-superuser role with no privileges, so the firstpg_rewind Patroni attempted after a failover failed with "permission denied for function pg_read_binary_file", leaving the demoted primary unable to rejoin the cluster as a replica.

This fix grants the rewind user EXECUTE on the three pg_catalog functions pg_rewind requires (pg_ls_dir, pg_stat_file,pg_read_binary_file), matching what Patroni itself grants during bootstrap. Re-running tpaexec deploy on an existing cluster applies the fix.

Fixed an issue whereby Patroni REST API test and management calls could fail under mTLS with a non-root SSH user.

Calls to Patroni's REST API, used by tpaexec test and by switchover/restart management operations, could fail with a permission-denied connection error when the cluster used mTLS authentication for the API and the connecting SSH user was not root - the recommended configuration on AWS and bare metal. This no longer happens.

Fixed an issue whereby a pgbouncer/pgd-proxy port clash on the read-only port went undetected.

TPA already stopped a deploy if pgbouncer and pgd-proxy were both configured to listen on the same port on the same host, but it only checked the main (read-write) port. If the clash was instead on pgd-proxy's read-only port, TPA didn't notice, and one of the two services could quietly fail to start.

Deploy now checks both ports for a clash, and fails with a clear message, instead of stopping abruptly with a confusing error, if pgd-proxy's listen port isn't set in config.yml at all.

Deploy also now stops with a clear message if a host runs pgd-proxy but its read-only port (read_listen_port) isn't set. Whenbdr_package_version isn't set in config.yml, TPA assumes BDR 5.5 or later, which needs this port, so it requires read_listen_port rather than letting pgd-proxy start without read-only routing.

Fixed an issue whereby pgd-cli was installed but not configured on proxy nodes during a BDR 4 to PGD 5 upgrade.

A BDR-Always-ON to PGD-Always-ON major upgrade (BDR 4 to PGD 5) converts dedicated harp-proxy nodes into pgd-proxy nodes, which require pgd-cli. The upgrade installed the pgd-cli package on those nodes but never wrote its configuration file, leaving pgd-cli present but unusable there (/etc/edb/pgd-cli/pgd-cli-config.yml was absent). The upgrade reported success regardless, so the problem was silent.

TPA now writes the pgd-cli configuration on those nodes during the upgrade, so pgd-cli is fully installed and configured on the new pgd-proxy nodes.

Fixed an issue whereby pgd-cli authentication failed on dedicated pgd-proxy nodes.

On a dedicated pgd-proxy node (one with no postgres/bdr role), pgd-cli was configured with endpoints that connect as the Postgres superuser, but the node's .pgpass holds only the pgd-proxy user's password. As a result, pgd-cli could not authenticate against any endpoint and failed with fe_sendauth: no password supplied.

TPA now sets each pgd-cli endpoint to connect as the user appropriate to the node running pgd-cli, the pgd-proxy user on dedicated pgd-proxy nodes, so pgd-cli works out of the box there. Postgres and BDR nodes are unaffected.

Fixed an issue whereby the psycopg2 canary test failed on clusters with a non-root login user.

tpaexec test aborted at "Install psycopg2 import canary script" with "Destination /etc/tpa not writable" on any cluster whose ansible_useris not root, such as a typical AWS or bare-metal cluster. The test now installs and removes its canary script with the privileges it requires, so the psycopg2 import check runs as intended regardless of the login user.

Fixed an issue whereby Barman package installation failed on Debian/Ubuntu for Barman 3.20 and later.

Since Barman 3.20.0, installing from EDB's own repository on Debian or Ubuntu ships Barman's Python client library under a new package name,edb-python312-barman, instead of python3-barman. TPA now selects the correct package name automatically, so deployments and upgrades to Barman 3.20 or later succeed on Debian and Ubuntu when using EDB's repositories. Installs from the PGDG repository, and all RedHat/SUSE installs, are unaffected.

Fixed an issue whereby TPA's generated ssh_config prevented Ansible Tower's own SSH credential from being used.

When a cluster is managed by Ansible Tower, TPA no longer writes anIdentityFile or IdentitiesOnly setting into the cluster'sssh_config. Tower supplies the SSH key through its own machine credential, and pinning TPA's own key here prevented that credential from being used, which forced operators to overrideansible_ssh_common_args by hand after every provision.

The generated ssh_config still sets the connection port, the cluster's known_hosts files, and ServerAliveInterval, so Tower clusters now get the correct SSH behavior out of the box with no manual editing. Clusters that are not managed by Tower are unaffected.

61496
Fixed an issue whereby a HARP cluster could become unroutable after a re-deploy.

TPA now re-applies the HARP cluster bootstrap configuration when the consensus store (DCS) has lost it, not only when the on-disk bootstrap file has changed. Previously, if the DCS was emptied or re-provisioned, or an initial bootstrap was interrupted, while the bootstrap file was left unchanged, a re-deploy would silently skip re-applying it and leave HARP-proxy unable to route connections.

Fixed an issue whereby tpaexec upgrade --components=pg-backup-api was a silent no-op.

Upgrading pg-backup-api via tpaexec upgrade --components=pg-backup-apidid nothing unless a specific package version was pinned inconfig.yml, even when a newer version was available. It now upgrades to the latest available version by default, matching barman, pgbouncer, and PEM.

Fixed an issue whereby redeploying could reset the certificate ownership of a TLS-using service colocated with Postgres.

Redeploying a cluster where a TLS-using service (for example etcd) shared a node with Postgres could leave that service's certificate and CA files owned by the Postgres system user instead of the service's own user, breaking TLS for that service until the files were manually fixed. This no longer happens.

Fixed an issue whereby the pkg-config package was missing from the required package list for Debian-based systems.

The pkg-config package was missing from the list of required packages for Debian-based systems, causing build failures when compiling software that relies on it. pkg-config has been added to the list of required packages, so builds from source now proceed without errors related to this missing dependency.

Fixed an issue whereby tpaexec switchover failed on EFM clusters.

tpaexec switchover on a cluster with failover_manager: efm no longer fails after promotion with a "requested handler ... was not found" error while regenerating EFM configuration for the new topology.

Fixed an issue whereby M1 deploys failed when efm tasks were excluded.

Deploying an M1 cluster configured with --enable-efm using tpaexec deploy --excluded-tasks=efm failed on the primary with "Role 'efm_role' does not exist": the task granting privileges toefm_role did not honor the task selector, while the tasks that create the role did. The grant tasks are now skipped along with the rest of the efm tasks. In addition, the replication user's .pgpass entry was only written by the (excluded) efm role, leaving pg_basebackupwaiting forever for a password when cloning the replica; the entry is now written regardless of the task selector.

Fixed an issue whereby upgrading pem-agent with update_hosts could fail when restricted to a subset of hosts.

Upgrading the pem-agent component with update_hosts restricted to a subset of hosts could fail with an undefined-variable error on any PEM agent host excluded from that subset. The restart step now only runs against the hosts actually being upgraded.

Fixed an issue whereby enabling pg-backup-api without PEM or beacon-agent produced a configuration with no EDB repository enabled.

pg-backup-api is only published to EDB's Cloudsmith repositories, never to PGDG. Configuring a community-Postgres cluster with--enable-pg-backup-api (without --enable-pem or--enable-beacon-agent) previously produced a config.yml with an empty edb_repositories list, so the generated configuration could not install pg-backup-api. TPA now enables the standard EDB repository whenever --enable-pg-backup-api is used, matching the existing behavior for --enable-pem and --enable-beacon-agent.

Fixed an issue whereby PGD-X/PGD-S minor version upgrades could fail spuriously on clusters using non-default Connection Manager ports.

The listening-ports check run during PGD-X/PGD-S minor version upgrades always checked the generic default Connection Manager ports instead of the ports actually configured for the cluster's node group, causing the check to fail with a connection error on any cluster that configures non-default read_write_port/read_only_port values.

Fixed an issue whereby Postgres user and role DDL could fail during BDR3/BDR4-to-PGD5 or PGD5-to-PGD6 major version upgrades.

During a BDR3-to-PGD5, BDR4-to-PGD5, or PGD5-to-PGD6 (PGD-X) major version upgrade, TPA could run Postgres user and role DDL (creating users, granting roles) on a node immediately after restarting it, before BDR Raft consensus had stabilized and before the node was unfenced. This could cause replicated DDL to fail with errors such as "failed to get a DDL epoch" or "consensus request timed out".

TPA now waits for Raft consensus to stabilize before running this DDL, and only unfences the node afterwards, matching the correct sequence: fence, stop/update/restart Postgres, wait for consensus, run DDL, unfence.

61496
Fixed an issue whereby PostgreSQL could be installed from the OS repository instead of PGDG/EDB on RHEL, Rocky Linux, AlmaLinux, CentOS Stream, and Oracle Linux 10.

On RHEL, Rocky Linux, AlmaLinux, CentOS Stream, and Oracle Linux 10, the OS BaseOS/AppStream repositories ship their own PostgreSQL packages. Because DNF modularity, which TPA previously relied on to keep the OS repositories from providing PostgreSQL, was removed in these EL10 distributions, TPA could end up installing PostgreSQL from the OS repository instead of PGDG or EDB. The OS package's systemd unit is named differently from the one TPA expects, so deployment then failed while trying to manage the PostgreSQL service.

TPA now excludes PostgreSQL, Barman, and repmgr packages from the OS BaseOS and AppStream repositories on all of these EL10 distributions, so PostgreSQL is always installed from PGDG or EDB as intended. This matches the exclusion behavior already in place for earlier RHEL family versions (7, 8, and 9, which rely on DNF module exclusion).

Fixed an issue whereby the Patroni readiness check could give up early despite its retry budget.

The wait for a Patroni node to report itself ready during deploy, switchover, and tpaexec test could abandon its 3-minute retry budget after only a few seconds, causing spurious failures on nodes whose Patroni API was simply slow to start listening. When the wait does fail, TPA now includes a recent excerpt of Patroni's own log in the error, making the underlying cause visible without logging in to the node.

Fixed an issue whereby newly generated cluster CAs lacked an X509v3 Key Usage extension.

TPA's generated cluster CA carried no X509v3 Key Usage extension. Python 3.13 enables strict X.509 verification by default, and strict verification rejects a CA certificate with no keyUsage extension at all, so any Python TLS client running on a node with Python 3.13 or newer (for example Debian 13) and verifying against TPA's CA would fail, even though the CA itself was otherwise valid.

This fix adds the required keyUsage extension to newly generated CAs. Existing clusters are not affected: a CA already on disk keeps working exactly as before and is never regenerated by this change. If you later need a fixed CA for an existing cluster (for example, before adding a node running Python 3.13 or newer), delete <cluster_dir>/ssl/CA.crt(keep CA.key) and redeploy to have it re-signed with the new extension.

Fixed an issue whereby Connection Manager ports were not applied correctly when local routing was enabled.

PGD reads the Connection Manager options (read_write_port,read_only_port, http_port, and use_https) only from the node group that has routing enabled. With --pgd-routing local that is each location subgroup, but tpaexec configure wrote the ports to the top-level group, where they had no effect: Connection Manager silently fell back to listening on postgres_port + 1000 andpostgres_port + 1001 instead of the requested ports.

tpaexec configure now places these options on the location subgroups when local routing is selected, and on the top-level group when global routing is selected. Existing clusters do not need their config.ymledited: a routing-enabled subgroup that does not set these options itself now inherits them from its parent group, so redeploying moves Connection Manager onto the configured ports.

Fixed an issue whereby update_hosts scoping could cause PGD5-to-PGD6 and PGD6 minor upgrades to fail or skip proxy downtime monitoring.

Several plays in the PGD5-to-PGD6 major upgrade and PGD6 minor upgrade playbooks were incorrectly scoped to the update_hosts subset when they actually depend on cluster-wide state (the connection manager endpoint for every node, and write-leader detection). This caused upgrades to fail or silently skip proxy downtime monitoring wheneverupdate_hosts was used to upgrade a subset of hosts that excluded the cluster's current primary or write leader. These plays now always run across the whole cluster, regardless of update_hosts.

Deprecations

Description
PGD-S is no longer accepted as an architecture at configure time.

PGD-S (PGD Essential) is no longer offered as a product. tpaexec configure --architecture PGD-S now fails immediately with a clear error instead of creating a cluster. The same check applies totpaexec reconfigure and tpaexec provision/deploy against an existing cluster whose config.yml still specifies architecture: PGD-S. Use PGD-X for new PGD 6 deployments instead.