This is the multi-page printable view of this section. .
Administration
- 1: Managing PostgreSQL Clusters
- 2: Managing PostgreSQL Users
- 3: Managing PostgreSQL Databases
- 4: Patroni HA Management
- 5: Managing PostgreSQL HBA Rules
- 6: Pgbouncer Connection Pooling
- 7: Managing PostgreSQL Component Services
- 8: Manage PostgreSQL Cron Jobs
- 9: Managing PostgreSQL Extensions
- 10: Upgrading PostgreSQL Major/Minor Versions
1 - Managing PostgreSQL Clusters
Quick Reference
| Action | Command | Description |
|---|---|---|
| Create Cluster | bin/pgsql-add <cls> |
Create a new PostgreSQL cluster |
| Expand Cluster | bin/pgsql-add <cls> <ip...> |
Add replica to existing cluster |
| Shrink Cluster | bin/pgsql-rm <cls> <ip...> |
Remove instance from cluster |
| Remove Cluster | bin/pgsql-rm <cls> |
Destroy entire PostgreSQL cluster |
| Reload Service | bin/pgsql-svc <cls> [ip...] |
Reload cluster load balancer config |
| Reload HBA | bin/pgsql-hba <cls> [ip...] |
Reload cluster HBA access rules |
| Clone Cluster | - | Clone via standby cluster or PITR |
For other management tasks, see: HA Management, Manage Users, Manage Databases.
Create Cluster
To create a new PostgreSQL cluster, first define the cluster in the inventory, then add nodes and initialize:
On managed nodes, create the cluster with: (Execute pgsql.yml playbook on <cls> group)
Example: Create 3-node PG cluster pg-test
If you re-run create on an existing cluster, Pigsty won’t remove existing data files, but service configs will be overwritten and the cluster will restart!
Additionally, if you specified a baseline SQL in database definition, it will re-execute - if it contains delete/overwrite logic, data loss may occur.
Expand Cluster
To add a new replica to an existing PostgreSQL cluster, add the instance definition to inventory: all.children.<cls>.hosts.
Scaling out is similar to creating a cluster. First add the new node to Pigsty: Add Node:
Then run the following on the new node to scale out (Install PGSQL module on new node with same pg_cluster):
After scaling, you should Reload Service to add the new member to load balancer.
Example: Add replica 10.10.10.13 to 2-node cluster pg-test
Shrink Cluster
To remove a replica from an existing PostgreSQL cluster, remove the instance definition from inventory all.children.<cls>.hosts.
Scale-in stops the instance and deletes its data directory by default. First run pig pg list <cls> and pig pb info, verify that the target is not the primary and that a recent restorable backup exists,
then have the operator enter the exact <ip> and execute only after confirmation.
First uninstall PGSQL module from target node (Execute pgsql-rm.yml on <ip>):
After removing PGSQL module, optionally remove the node from Pigsty: Remove Node:
After scaling in, remove the instance from inventory, then Reload Service to remove it from load balancer.
Example: Remove replica 10.10.10.13 from 3-node cluster pg-test
Remove Cluster
To destroy a cluster, uninstall PGSQL module from all nodes (Execute pgsql-rm.yml on <cls>):
This is irreversible data deletion. Inspect pig pg list <cls> and pig pb info, verify a recent backup and any independent copy to retain,
and have the operator enter the exact cluster name. The commands below perform the corresponding destruction directly.
After destroying PGSQL, optionally remove all nodes from Pigsty: Remove Node (optional if other services exist):
After removal, delete the entire cluster definition from inventory.
Example: Destroy 3-node PG cluster pg-test
Note: If pg_safeguard is configured (or globally true), pgsql-rm.yml will abort to prevent accidental removal.
Override with playbook command line to force removal.
By default, cluster backup repo is deleted with the cluster. To preserve backups (e.g., with centralized repo), set pg_rm_backup=false:
Reload Service
PostgreSQL clusters expose services via HAProxy on host nodes. When service definitions, instance weights, or cluster membership change (for example, scale out or scale in), reload services to update HAProxy’s static member configuration. The default Primary and Replica services detect the current role through Patroni REST API health checks, so ordinary switchover or failover reroutes automatically and does not require regenerating HAProxy configuration.
To reload service config on entire cluster or specific instances (Execute pg_service subtask of pgsql.yml on <cls> or <ip>):
If you use a dedicated load-balancer cluster (pg_service_provider), only reloading the cluster primary updates the load-balancer configuration.
Example: Reload pg-test cluster service config
Reload HBA
When HBA configs change, reload HBA rules to apply. (pg_hba_rules / pgb_hba_rules)
If you have inventory-role-specific HBA rules or address ranges that reference cluster member aliases, reload HBA after changing pg_role labels or scaling the cluster. Role selectors use static inventory variables and do not change automatically after a Patroni switchover.
To reload PG and Pgbouncer HBA rules on entire cluster or specific instances (Execute HBA subtasks of pgsql.yml on <cls> or <ip>):
Example: Reload pg-test cluster HBA rules
Config Cluster
PostgreSQL config params are managed by Patroni. Initial params are specified by Patroni config template.
After cluster init, config is stored in Etcd, dynamically managed and synced by Patroni.
Most Patroni config params can be modified via patronictl.
Other params (e.g., etcd DCS config, log/RestAPI config) can be updated via subtasks. For example, when etcd cluster membership changes, refresh Patroni config:
You can override Patroni-managed defaults at different levels: specify params per instance, specify params per user, or specify params per database.
Clone Cluster
Two ways to clone a cluster: use Standby Cluster, or use Point-in-Time Recovery. The former is simple and requires no backup repository, but it does require a reachable replication upstream and can clone only the latest state. The latter requires a centralized backup repository such as Silo and can clone to any point within the retention period.
| Method | Pros | Cons | Use Cases |
|---|---|---|---|
| Standby Cluster | No backup repository needed | Requires reachable upstream; latest state only | DR, read-write separation, migration |
| PITR | Recover to any point | Requires centralized backup | Undo mistakes, data audit |
Clone via Standby Cluster
Standby Cluster continuously syncs from upstream cluster via streaming replication - the simplest cloning method.
Specify pg_upstream on the new cluster primary to auto-pull data from upstream.
Create standby cluster with:
Standby cluster follows upstream, keeping data in sync. Promote to independent cluster anytime:
Via Config Cluster, remove standby_cluster config to promote:
After promotion, pg-test2 becomes independent cluster accepting writes, forked from pg-test.
If upstream cluster switchover occurs, change standby cluster upstream via Config Cluster:
Clone via PITR
Point-in-Time Recovery (PITR) allows recovery to any point within backup retention. Requires a centralized backup repository (Silo/S3), but is more powerful.
To clone via PITR, add pg_pitr param specifying recovery target:
Execute clone with pgsql-pitr.yml playbook:
PITR supports multiple recovery target types:
| Target Type | Example | Description |
|---|---|---|
| Time | time: "2025-01-10 10:00:00+00" |
Recover to specific timestamp |
| XID | xid: "250000" |
Recover to before/after txn |
| Name | name: "before_migration" |
Recover to named restore point |
| LSN | lsn: "0/4001C80" |
Recover to specific WAL pos |
| Latest | pg_pitr: {} |
Recover to end of WAL archive |
Pigsty v5.0 PITR keeps archiving enabled by default (archive: true). If you explicitly set archive: false for exploratory recovery, reset archive_mode, restart the cluster, and perform a new full backup after confirming the recovered data is correct:
For detailed PITR usage, see Restore Operations documentation.
2 - Managing PostgreSQL Users
Quick Start
Pigsty uses declarative management: first define users in the inventory, then use bin/pgsql-user <cls> <username> to create or modify.
For the complete user definition reference, see User Configuration. See Access Control for roles and privileges, and Authentication for credential management.
name is the key used by pgsql-user.yml to look up a user definition; the playbook does not rename roles. For a rename, create the replacement role, migrate ownership, memberships, and client credentials, validate the cutover, and only then remove the old role. Do not treat delete-and-create as a lossless rename.
| Action | Command | Description |
|---|---|---|
| Create User | bin/pgsql-user <cls> <user> |
Create new business user or role |
| Modify User | bin/pgsql-user <cls> <user> |
Modify existing user properties |
| Delete User | bin/pgsql-user <cls> <user> |
Dependency-aware destructive deletion (state: absent) |
Create User
Users defined in pg_users are auto-created during PostgreSQL cluster creation in the pg_user task.
To create a new user on an existing cluster, add user definition to all.children.<cls>.pg_users, then execute:
Example: Create business user dbuser_app
Result: Creates dbuser_app user on primary, sets password, grants dbrole_readwrite role, adds to Pgbouncer pool, reloads Pgbouncer config on all instances.
For manual user creation, you must ensure Pgbouncer user list sync yourself.
Modify User
Same command as create - playbook is idempotent. When target user exists, Pigsty modifies properties to match config.
Not directly mutable: name is the identity key in the declarative definition. The playbook does not rename an existing role. Use a controlled create, ownership/privilege and client migration, validation, and old-role removal sequence.
All other properties can be modified. Common examples:
Modify password: Update password field. Logging is temporarily disabled during password change to prevent leakage.
Modify privilege attributes: Configure boolean flags for user privileges.
Modify expiration: Use expire_in for relative expiry (N days), or expire_at for absolute date. expire_in takes priority and recalculates on each playbook run - good for temp users needing periodic renewal.
Modify role membership: Use roles array with simple or extended format. Role membership is additive - won’t remove undeclared existing roles. Use state: absent to explicitly revoke.
Manage user parameters: Use parameters dict for user-level params, generates ALTER USER ... SET. Use DEFAULT to reset.
Connection pool config: Set pgbouncer: true to add user to pool. Optional pool_mode and pool_connlimit.
Delete User
Deleting a user terminates sessions, transfers object ownership, revokes grants, and runs DROP ROLE; it is irreversible. Confirm the exact cluster, role, successor owner, and a recent backup before setting the user to state: absent and applying the change.
Config example:
Deletion process: On the primary, the task runs pg-drop-role <user> postgres --force. It disables login, terminates active sessions, transfers database and tablespace ownership plus objects in each connectable database to postgres, runs DROP OWNED to remove grants, revokes role memberships, and finally runs DROP ROLE. A pre-change audit snapshot is written to /tmp/pg_drop_role_<user>_<timestamp>.log.
Protection: The Ansible task skips postgres and the replication, admin, and monitor usernames configured in inventory. When invoked directly, pg-drop-role protects only the hard-coded default names postgres, replicator, dbuser_dba, and dbuser_monitor; renamed system accounts are not recognized automatically.
pg-drop-role skips DROP OWNED in a database if its preceding REASSIGN OWNED fails, but the cross-database procedure is not one transaction. A mid-run failure can leave the role NOLOGIN, some ownership already transferred, or dependencies still present. The v4.5 Ansible task also uses ignore_errors, so a playbook result is not sufficient evidence. Verify role absence, successor ownership, application cutover, and the audit log afterward.
In v4.5, pgsql-user.yml reloads Pgbouncer but does not reliably prune a deleted role from /etc/pgbouncer/userlist.txt. Check every cluster instance after deletion:
If an exact Pgbouncer entry remains, remove that single line under change control, reload Pgbouncer, and validate application connections. Do not use a broad pattern to delete entries.
Manual Deletion
For manual user deletion, use pg-drop-role script directly:
Common Use Cases
Common user configuration examples:
Basic business user
Read-only user
Admin user (can execute DDL)
Temp user (expires in 30 days)
Role (no login, for permission grouping)
User with advanced role options (PG16+)
Query Users
Common SQL queries for user info:
List all users
View user role membership
View user-level parameters
View expiring users
Connection Pool Management
Connection pool params in user definitions are applied to Pgbouncer when creating/modifying users.
Users with pgbouncer: true are added to /etc/pgbouncer/userlist.txt. User-level pool params (pool_mode, pool_connlimit) are configured via /etc/pgbouncer/useropts.txt.
Use postgres OS user with pgb alias to access Pgbouncer admin database. For more pool management, see Pgbouncer Management.
Manage Default-User Passwords
For a business user, follow Modify User: persist the new password in its pg_users definition, preview the scoped playbook, and then apply it. The three default users require extra coordination because other services consume their credentials.
| Parameter | Default | Role | Consumers |
|---|---|---|---|
pg_admin_password |
DBUser.DBA |
dbuser_dba |
Admin clients, Pgbouncer, Infra service files, pgAdmin |
pg_monitor_password |
DBUser.Monitor |
dbuser_monitor |
Exporters, Pgbouncer, Grafana data sources |
pg_replication_password |
DBUser.Replicator |
replicator |
Patroni replication and .pgpass files |
These accounts belong to pg_default_roles, not pg_users. pgsql-user.yml looks up only pg_users, so do not rotate a default password by overriding pg_users on the command line: that changes the business-user list visible to that run and exposes plaintext in shell history.
Rotate one account at a time:
- Persist the new parameter in
pigsty.ymlor the inventory actually in use; never put the plaintext password on the command line. - On the current primary, open interactive
psqlas a superuser and run\password <username>; the meta-command reads the secret interactively. - Run the corresponding refresh playbooks below after verifying the
-lcluster/node scope. - Keep the current administration session open and verify direct PostgreSQL, Pgbouncer, replication, exporters, and Grafana data sources before rotating another account.
Refresh every consumer for the account. Replace <cls> and constrain infra to the actual targets:
A mismatch between the replication role and Patroni nodes prevents new replication connections, so rotate that credential in a maintenance window and validate promptly. If VIBE or another module has rendered an admin connection string into its workspace context, rerender that module’s files as well.
In v4.5, env_pgpass adds the new line with lineinfile; it does not remove older lines by username. Because libpq uses the first matching line, inspect every target Infra node after the refresh and remove obsolete entries through controlled editing without printing secrets:
patroni_password protects the Patroni REST API; it is not a PostgreSQL role password. After changing it in inventory, refresh the target PostgreSQL cluster and Infra management side separately:
Then validate authentication and cluster state with patronictl or pig pg list <cls>.
3 - Managing PostgreSQL Databases
Quick Start
Pigsty uses declarative management: first define databases in the inventory, then use bin/pgsql-db <cls> <dbname> to create or modify.
For the complete database definition reference, see Database Configuration. For database access permissions, see Access Control: Database Isolation.
Note: Some parameters can only be specified at creation time. Modifying these requires recreating the database (use state: recreate).
| Action | Command | Description |
|---|---|---|
| Create Database | bin/pgsql-db <cls> <db> |
Create new business database |
| Modify Database | bin/pgsql-db <cls> <db> |
Modify existing database properties |
| Delete Database | bin/pgsql-db <cls> <db> |
Delete database (requires state: absent) |
| Rebuild Database | bin/pgsql-db <cls> <db> |
Drop and recreate (requires state: recreate) |
| Clone Database | bin/pgsql-db <cls> <db> |
Clone database using template |
Create Database
Databases defined in pg_databases are auto-created during PostgreSQL cluster creation in the pg_db task.
To create a new database on an existing cluster, add database definition to all.children.<cls>.pg_databases, then execute:
Example: Create business database myapp
Result: Creates myapp database on primary, sets owner to dbuser_myapp, creates app schema, enables pg_trgm and btree_gin extensions. Database is auto-added to Pgbouncer pool and registered as Grafana datasource.
For manual database creation, you must ensure Pgbouncer pool and Grafana datasource sync yourself.
Modify Database
Same command as create - playbook is idempotent when no baseline SQL is defined.
When target database exists, Pigsty modifies properties to match config. However, some properties can only be set at creation.
Immutable properties: These can’t be modified after creation, require state: recreate:
name(database name),template,strategy(clone strategy)encoding,locale/lc_collate/lc_ctype,locale_provider/icu_locale/icu_rules/builtin_locale
All other properties can be modified. Common examples:
Modify owner: Update owner field, executes ALTER DATABASE ... OWNER TO and grants permissions.
Modify connection limit: Use connlimit to limit max connections.
Revoke public connect: Setting revokeconn: true revokes PUBLIC CONNECT privilege, allowing only owner, DBA, monitor, and replication users.
Manage parameters: Use parameters dict for database-level params, generates ALTER DATABASE ... SET. Use special value DEFAULT to reset.
Manage schemas: Use schemas array with simple or extended format. Use state: absent to drop (CASCADE).
Manage extensions: Use extensions array with simple or extended format. Use state: absent to uninstall (CASCADE).
Dropping schemas or uninstalling extensions uses CASCADE, deleting all dependent objects. Understand impact before executing.
Connection pool config: By default all databases are added to Pgbouncer. Configure pgbouncer, pool_mode, pool_size, pool_reserve, pool_size_min, pool_connlimit, and pool_auth_user.
Since Pigsty
v4.1.0, database pool fields are unified aspool_reserveandpool_connlimit; legacy aliasespool_size_reserve/pool_max_db_connare converged.
Delete Database
To delete a database, set state to absent and execute:
Config example:
Deletion process: If is_template: true, first executes ALTER DATABASE ... IS_TEMPLATE false; uses DROP DATABASE ... WITH (FORCE) (PG13+) to force drop and terminate all connections; removes from Pgbouncer pool; unregisters from Grafana datasource.
Protection: System databases postgres, template0, template1 cannot be deleted. Deletion only runs on primary - streaming replication syncs to replicas.
Database deletion is irreversible - permanently deletes all data. Before executing: ensure recent backup exists, confirm no business uses the database, notify stakeholders. Pigsty is not responsible for any data loss from database deletion. Use at your own risk.
Rebuild Database
recreate state rebuilds database (drop then create):
Config example:
Use cases: Test environment reset, clear dev database, modify immutable properties (encoding, locale), restore to initial state.
Difference from manual DROP + CREATE: Single command; auto-preserves Pgbouncer and Grafana config; auto-loads baseline init script.
Clone Database
Clone PostgreSQL databases using PG template mechanism. During cloning, no active connections to template database are allowed.
Config example:
Instant Clone (PG18+): If using PostgreSQL 18+, Pigsty defaults file_copy_method. With strategy: FILE_COPY, database clone completes in ~200ms without copying data files. E.g., cloning 30GB database: normal takes 18s, instant takes 200ms.
Manual clone: Ensure all connections to template are terminated:
Limitations: Instant clone only available on supported filesystems (xfs, btrfs, zfs, apfs); don’t use postgres database as template; in high-concurrency environments, all template connections must be cleared within clone window (~200ms).
Connection Pool Management
Connection pool params in database definitions are applied to Pgbouncer when creating/modifying databases.
By default all databases are added to Pgbouncer pool (pgbouncer: true). Databases are added to /etc/pgbouncer/database.txt. Database-level pool params (pool_auth_user, pool_mode, pool_size, pool_reserve, pool_size_min, pool_connlimit) are configured via this file.
Use postgres OS user with pgb alias to access Pgbouncer admin database. For more pool management, see Pgbouncer Management.
4 - Patroni HA Management
Overview
Pigsty uses Patroni to manage PostgreSQL clusters. It handles config changes, status checks, switchover, restart, reinit replicas, and more.
To use Patroni for management, you need one of the following identities:
- From INFRA node as admin user, managing all clusters in the environment.
- From PGSQL node as
pg_dbsu(defaultpostgres), managing the current cluster only.
Patroni provides patronictl CLI for management. Pigsty provides a wrapper alias pg to simplify operations.
Available Commands
| Command | Function | Description |
|---|---|---|
edit-config |
Edit Config | Interactively edit cluster Patroni/PostgreSQL config |
list |
List Status | List cluster members and their status |
switchover |
Switchover | Switch primary role to specified replica (planned) |
failover |
Failover | Force failover to specified replica (emergency) |
restart |
Restart | Restart PostgreSQL instance to apply restart-required params |
reload |
Reload | Reload Patroni config (no restart needed) |
reinit |
Reinit Replica | Reinitialize replica (wipe data and re-clone) |
pause |
Pause Auto-Failover | Pause Patroni automatic failover |
resume |
Resume Auto-Failover | Resume Patroni automatic failover |
history |
View History | Show cluster failover history |
show-config |
Show Config | Display current cluster config (read-only) |
query |
Execute Query | Execute SQL query on cluster members |
topology |
View Topology | Display cluster replication topology |
version |
View Version | Display Patroni version info |
remove |
Remove Member | Remove cluster member from DCS (dangerous) |
Edit Config
Use edit-config to interactively edit cluster Patroni and PostgreSQL config. This opens an editor to modify config stored in DCS, automatically applying changes to all members. You can change Patroni params (ttl, loop_wait, synchronous_mode, etc.) and PostgreSQL params in postgresql.parameters.
Common config modification examples:
Some params require PostgreSQL restart to take effect. Use pg list to check - instances marked with * need restart. Then use pg restart to apply.
You can also use curl or programs to call Patroni REST API:
List Status
Use list to view cluster members and status. Output shows each instance’s name, host, role, state, timeline, and replication lag. This is the most commonly used command for checking cluster health.
Example output:
Column descriptions: Member is instance name, composed of pg_cluster-pg_seq; Host is instance IP; Role is role type - Leader (primary), Replica, Sync Standby, Standby Leader (cascade primary); State is running state - running, streaming, in archive recovery, starting, stopped, etc.; TL is timeline number, incremented after each switchover; Lag in MB is replication lag in MB (not shown for primary).
Instances requiring restart show * after the name:
Switchover
Use switchover for planned primary-replica switchover. Switchover is graceful: Patroni ensures replica is fully synced, demotes primary, then promotes target replica. Takes seconds with brief write unavailability. Use for primary host maintenance, upgrades, or migrating primary to better nodes.
Before switchover, ensure all replicas are healthy (running or streaming), replication lag is acceptable, and stakeholders are notified.
After switchover, use pg list to confirm new cluster topology.
Failover
Use failover for emergency failover. Unlike switchover, failover is for when primary is unavailable. It directly promotes a replica without waiting for original primary confirmation. Since replicas may not be fully synced, failover may cause minor data loss. Use switchover for non-emergency situations.
Failover examples:
Switchover vs Failover: Switchover is for planned maintenance, requires original primary online, ensures full sync before switching, no data loss; Failover is for emergency recovery, original primary can be offline, directly promotes replica, may lose unsynced data. Use Switchover for daily maintenance/upgrades; use Failover only when primary is completely down and unrecoverable.
The built-in Patroni
failoversubcommand currently has no--leaderoption. Use plannedswitchover --leader ...when you need to validate or name the old primary; failover accepts only the candidate replica.
Restart
Use restart to restart PostgreSQL instances, typically to apply restart-required parameter changes. When run against the whole cluster, patronictl submits each selected member in turn but does not guarantee a replica-first, leader-last order. If that order matters, restart replicas by role and then restart the leader separately.
After modifying restart-required params (shared_buffers, shared_preload_libraries, max_connections, max_worker_processes, etc.), use this command.
Reload
Use reload to reload Patroni config without restarting PostgreSQL. This re-reads config files and applies non-restart params via pg_reload_conf(). Lighter than restart - doesn’t interrupt connections or running queries.
Most PostgreSQL params work via reload. Only postmaster-context params (shared_buffers, max_connections, shared_preload_libraries, archive_mode, etc.) require restart.
Reinit Replica
Use reinit to reinitialize a replica. This deletes all data on the replica and rebuilds it according to Patroni’s create_replica_methods order. Pigsty tries basebackup (pg_basebackup) first by default; when a remote pgBackRest repository is enabled, pgbackrest is also configured as a fallback. Use this when replica data is corrupted, the replica is too far behind and required WAL has been removed, or replica configuration must be reset.
This operation deletes all data on the target instance. Run it only on a replica, never on the primary.
During rebuild, use pg list to check progress. Replica state shows creating replica:
Pause
Use pause to pause Patroni automatic failover. When paused, Patroni won’t auto-promote replicas even if primary fails. Use for planned maintenance windows (prevent accidental triggers), debugging (prevent cluster state changes), or manual switchover timing control.
While paused, the cluster will not recover automatically if the primary fails. Run resume after maintenance.
Resume
Use resume to resume Patroni automatic failover. Execute immediately after maintenance to ensure cluster auto-recovers on primary failure.
History
Use history to view cluster failover history. Each switchover (auto or manual) creates a new timeline record.
Column descriptions: TL is timeline number, incremented after each switchover, distinguishes primary histories; LSN is Log Sequence Number at switchover, marks WAL position; Reason is switchover reason - switchover to xxx (manual), failover to xxx (failure), or no recovery target specified (init); Timestamp is when switchover occurred.
Show Config
Use show-config to view current cluster config stored in DCS. This is read-only; use edit-config to modify.
Query
Use query to quickly execute SQL on cluster members. Convenient for debugging - for complex production queries, use psql or applications.
Topology
Use topology to view cluster replication topology as a tree. More intuitive than list for showing primary-replica relationships, especially for cascading replication.
In cascading replication, topology clearly shows replication hierarchy - e.g., pg-test-3 replicates from pg-test-2, which replicates from primary pg-test-1.
Version
Use version to view patronictl version.
Remove
Use remove to remove cluster or member metadata from DCS. This is dangerous - only removes DCS metadata, doesn’t stop PostgreSQL or delete data files. Misuse may cause cluster state inconsistency.
Normally you don’t need this command. To properly remove clusters/instances, use Pigsty’s bin/pgsql-rm script or pgsql-rm.yml playbook.
Only consider remove for: orphaned DCS metadata (node physically removed but metadata remains), or cluster destroyed via other means requiring metadata cleanup.
5 - Managing PostgreSQL HBA Rules
Quick Start
Pigsty uses declarative management: first define HBA rules in the inventory, then use bin/pgsql-hba <cls> to refresh.
For rule syntax, see HBA Configuration. For authentication methods, default boundaries, and credential management, see Authentication.
| Action | Description | Risk |
|---|---|---|
| Refresh HBA Rules | Re-render config files and reload service | Low |
| Verify HBA Rules | View current rules, test connection auth | Read |
| Common Scenarios | Add rules, block IP, role-based, post-expansion | Low |
| Troubleshooting | Connection rejected, auth failed, rules not applied | - |
| Pgbouncer HBA | Pgbouncer connection pool HBA management | Low |
Refresh HBA Rules
After modifying HBA rules in pigsty.yml, re-render config files and reload services.
Result: Renders PostgreSQL and Pgbouncer HBA config files based on inventory definitions, then reloads services to apply.
Config file locations
| Service | Config File Path | Template File |
|---|---|---|
| PostgreSQL | /pg/data/pg_hba.conf |
roles/pgsql/templates/pg_hba.conf |
| Pgbouncer | /etc/pgbouncer/pgb_hba.conf |
roles/pgsql/templates/pgbouncer.hba |
Directly editing /pg/data/pg_hba.conf or /etc/pgbouncer/pgb_hba.conf works temporarily, but will be overwritten next time Ansible playbook runs. All HBA rule changes should be in pigsty.yml, then execute bin/pgsql-hba to refresh.
Related Tags
| Tag | Description |
|---|---|
pg_hba |
Render PostgreSQL HBA config file |
pg_reload |
Reload PostgreSQL config (needs pg_reload=true) |
pgbouncer_hba |
Render Pgbouncer HBA config file |
pgbouncer_reload |
Reload Pgbouncer config |
Verify HBA Rules
After refreshing HBA rules, verify config is correctly applied.
View current HBA rules
Check HBA config syntax
Common Scenarios
Add New HBA Rule
Add rule to cluster config’s pg_hba_rules, then refresh:
Emergency IP Block
When detecting malicious IP, add high-priority (order: 0) deny rule:
Role-Based Rules
Configure different HBA rules for primary and replica using role parameter:
After refresh, rules auto-enable/disable based on instance’s pg_role.
Refresh HBA After Expansion
When cluster adds new instances, rules using addr: cluster need refresh to include new members:
Refresh HBA After Failover
After Patroni failover, instance pg_role may not match config. If HBA rules use role filtering, update config and refresh:
Troubleshooting
Connection Rejected
Symptom: FATAL: no pg_hba.conf entry for host "x.x.x.x", user "xxx", database "xxx"
Steps:
- Check current HBA rules, confirm if matching rule exists:
-
Confirm client IP, username, database matches any rule
-
Check rule order (HBA uses first-match-wins)
-
Add corresponding rule and refresh:
Authentication Failed
Symptom: FATAL: password authentication failed for user "xxx"
Steps:
- Confirm password is correct
- Check password encryption method (
pg_pwd_enc) compatibility with client - Check if user exists:
HBA Rules Not Applied
Steps:
- Confirm refresh command was executed
- Check if Ansible execution succeeded
- Confirm PostgreSQL reloaded:
- Check if config file was updated:
Rule Order Issues
HBA uses first-match-wins. If rules not working as expected:
- Check
ordervalues in rule definitions - Use
psql -c "TABLE pg_hba_file_rules"to view actual order - Adjust
ordervalues (lower numbers = higher priority)
Pgbouncer HBA
Pgbouncer HBA management is similar to PostgreSQL, with some differences.
Config differences
| Difference | PostgreSQL | Pgbouncer |
|---|---|---|
| Config file | /pg/data/pg_hba.conf |
/etc/pgbouncer/pgb_hba.conf |
| Replication | Supports db: replication |
Not supported |
| Local auth | Uses ident |
Uses peer |
Refresh Pgbouncer HBA
Best Practices
- Always manage in config files: Don’t edit
pg_hba.confdirectly - all changes throughpigsty.yml - Test environment first: HBA changes can cause connection issues - verify in test env first
- Use order for priority: Blocklist rules use
order: 0to ensure priority matching - Refresh promptly: Refresh HBA after adding/removing instances or failover
- Principle of least privilege: Only open necessary access - avoid
addr: world+auth: trust - Monitor auth failures: Watch for auth failures in
pg_stat_activity - Backup config: Backup
pigsty.ymlbefore important changes
Related Documentation
- HBA Configuration: HBA rule config syntax and parameter details
- User Management: User and role management operations
- Access Control: Role system and permission model
- Authentication: Authentication methods, default boundaries, and credential management
- Encrypted Communication: TLS and client certificate verification
6 - Pgbouncer Connection Pooling
Overview
Pigsty uses Pgbouncer as PostgreSQL connection pooling middleware, listening on port 6432 by default, proxying access to local PostgreSQL on port 5432.
This is an optional component. If you don’t have massive connections or need transaction pooling and query metrics, you can disable it, connect directly to the database, or keep it unused.
User & Database Management
Pgbouncer users and databases are auto-managed by Pigsty, applying database config and user config when creating databases and creating users.
Database Management: Databases defined in pg_databases are auto-added to Pgbouncer by default. Set pgbouncer: false to exclude specific databases.
User Management: Users defined in pg_users need explicit pgbouncer: true to be added to connection pool user list.
Since Pigsty
v4.1.0, database pool fields are unified aspool_reserveandpool_connlimit; legacy aliasespool_size_reserve/pool_max_db_connare converged.
Service Management
In Pigsty, PostgreSQL cluster Primary Service and Replica Service default to Pgbouncer port 6432.
To bypass connection pool and access PostgreSQL directly, customize pg_services, or set pg_default_service_dest to postgres.
Config Management
Pgbouncer config files are in /etc/pgbouncer/, generated and managed by Pigsty:
| File | Description |
|---|---|
pgbouncer.ini |
Main config, pool-level params |
database.txt |
Database list, database-level params |
userlist.txt |
User password list |
useropts.txt |
User-level pool params |
pgb_hba.conf |
HBA access control rules |
Pigsty auto-manages database.txt and userlist.txt, updating them when creating databases or creating users.
You can manually edit config then RELOAD to apply:
Pool Management
Pgbouncer runs as the same dbsu as PostgreSQL, default postgres OS user. Pigsty provides pgb alias for easy management:
Use pgb on database nodes to connect to Pgbouncer admin console for management commands and monitoring queries.
| Command | Function | Description |
|---|---|---|
PAUSE |
Pause | Pause database, wait for txn completion then disconnect |
RESUME |
Resume | Resume database paused by PAUSE/KILL/SUSPEND |
DISABLE |
Disable | Reject new client connections for database |
ENABLE |
Enable | Allow new client connections for database |
RECONNECT |
Reconnect | Gracefully close and rebuild server connections |
KILL |
Kill | Immediately disconnect all client and server connections |
KILL_CLIENT |
Kill Client | Terminate specific client connection |
SUSPEND |
Suspend | Flush buffers and stop listening, for online restart |
SHUTDOWN |
Shutdown | Shutdown Pgbouncer process |
RELOAD |
Reload | Reload config files |
WAIT_CLOSE |
Wait Close | Wait for server connections to close after RECONNECT/RELOAD |
| Monitor Commands | Monitor | View pool status, clients, servers, etc. |
PAUSE
Use PAUSE to pause database connections. Pgbouncer waits for active txn/session to complete based on pool mode, then disconnects server connections. New client requests are blocked until RESUME.
Typical use cases:
- Online backend database switch (e.g., update connection target after switchover)
- Maintenance operations requiring all connections disconnected
- Combined with
SUSPENDfor Pgbouncer online restart
After pause, SHOW DATABASES shows paused status:
RESUME
Use RESUME to restore databases paused by PAUSE, KILL, or SUSPEND, allowing new connections and resuming normal service.
DISABLE
Use DISABLE to disable a database, rejecting all new client connection requests. Existing connections are unaffected.
Typical use cases:
- Temporarily offline a database for maintenance
- Block new connections for safe database migration
- Gradually decommission a database being removed
ENABLE
Use ENABLE to enable a database previously disabled by DISABLE, accepting new client connections again.
RECONNECT
Use RECONNECT to gracefully rebuild server connections. Pgbouncer closes connections when released back to pool, creating new ones when needed.
Typical use cases:
- Refresh connections after backend database IP change
- Reroute traffic after switchover
- Rebuild connections after DNS update
After RECONNECT, use WAIT_CLOSE to wait for old connections to fully release.
KILL
Use KILL to immediately disconnect all client and server connections for a database. Unlike PAUSE, KILL doesn’t wait for transaction completion - forces immediate disconnect.
After KILL, new connections are blocked until RESUME.
KILL_CLIENT
Use KILL_CLIENT to terminate a specific client connection. Client ID can be obtained from SHOW CLIENTS output.
SUSPEND
Use SUSPEND to suspend Pgbouncer. Flushes all socket buffers and stops listening until RESUME.
SUSPEND is mainly for Pgbouncer online restart (zero-downtime upgrade):
SHUTDOWN
Use SHUTDOWN to shut down Pgbouncer process. Multiple shutdown modes supported:
| Mode | Description |
|---|---|
SHUTDOWN |
Immediately shutdown Pgbouncer |
WAIT_FOR_SERVERS |
Stop accepting new connections, wait for server release |
WAIT_FOR_CLIENTS |
Stop accepting new connections, wait for all clients disconnect, for rolling restart |
RELOAD
Use RELOAD to reload Pgbouncer config files. Dynamically updates most config params without process restart.
Pigsty provides playbook task to reload Pgbouncer config:
WAIT_CLOSE
Use WAIT_CLOSE to wait for server connections to finish closing. Typically used after RECONNECT or RELOAD to ensure old connections are fully released.
Monitoring
Pgbouncer provides rich SHOW commands for monitoring pool status:
| Command | Description |
|---|---|
SHOW HELP |
Show available commands |
SHOW DATABASES |
Show database config and status |
SHOW POOLS |
Show pool statistics |
SHOW CLIENTS |
Show client connection list |
SHOW SERVERS |
Show server connection list |
SHOW USERS |
Show user config |
SHOW STATS |
Show statistics (requests, bytes) |
SHOW STATS_TOTALS |
Show cumulative statistics |
SHOW STATS_AVERAGES |
Show average statistics |
SHOW CONFIG |
Show current config params |
SHOW MEM |
Show memory usage |
SHOW DNS_HOSTS |
Show DNS cached hostnames |
SHOW DNS_ZONES |
Show DNS cached zones |
SHOW SOCKETS |
Show open socket info |
SHOW ACTIVE_SOCKETS |
Show active sockets |
SHOW LISTS |
Show internal list counts |
SHOW FDS |
Show file descriptor usage |
SHOW STATE |
Show Pgbouncer running state |
SHOW VERSION |
Show Pgbouncer version |
Common monitoring examples:
For more monitoring command details, see Pgbouncer official docs.
Unix Signals
Pgbouncer supports Unix signal control, useful when admin console is unavailable:
| Signal | Equivalent Command | Description |
|---|---|---|
SIGHUP |
RELOAD |
Reload config files |
SIGTERM |
SHUTDOWN WAIT_FOR_CLIENTS |
Graceful shutdown, wait clients |
SIGINT |
SHUTDOWN WAIT_FOR_SERVERS |
Graceful shutdown, wait servers |
SIGQUIT |
SHUTDOWN |
Immediate shutdown |
SIGUSR1 |
PAUSE |
Pause all databases |
SIGUSR2 |
RESUME |
Resume all databases |
Traffic Switching
Pigsty-managed database routes live in /etc/pgbouncer/database.txt. To move one database’s Pgbouncer traffic to another node, edit that file, reload the configuration, then drain and rebuild existing server connections:
The
pgb-routefunction currently shipped in the source only edits/etc/pgbouncer/pgbouncer.ini. That file merely includesdatabase.txtand does not contain the generated per-databasehost=routes, so the function does not change managed database backends. Do not use it in place of the procedure above.
7 - Managing PostgreSQL Component Services
Overview
Pigsty’s PGSQL module consists of multiple components, each running as a systemd service on nodes. (pgbackrest is an exception)
Understanding these components and their management is essential for maintaining production PostgreSQL clusters.
| Component | Port | Service Name | Description |
|---|---|---|---|
| Patroni | 8008 |
patroni |
HA manager, manages PostgreSQL lifecycle |
| PostgreSQL | 5432 |
postgres |
Placeholder service, not used, for emergency |
| Pgbouncer | 6432 |
pgbouncer |
Connection pooling middleware, traffic entry |
| PgBackRest | - | - | pgBackRest has no daemon service |
| HAProxy | 543x |
haproxy |
Load balancer, exposes database services |
| pg_exporter | 9630 |
pg_exporter |
PostgreSQL metrics exporter |
| pgbouncer_exporter | 9631 |
pgbouncer_exporter |
Pgbouncer metrics exporter |
| vip-manager | - | vip-manager |
Optional, manages L2 VIP address floating |
Do NOT use systemctl directly to manage PostgreSQL service. PostgreSQL is managed by Patroni - use patronictl commands instead.
Direct PostgreSQL operations may cause Patroni state inconsistency and trigger unexpected failover. The postgres service is an emergency escape hatch when Patroni fails.
Quick Reference
| Operation | Command |
|---|---|
| Start | systemctl start <service> |
| Stop | systemctl stop <service> |
| Restart | systemctl restart <service> |
| Reload | systemctl reload <service> |
| Status | systemctl status <service> |
| Logs | journalctl -u <service> -f |
| Enable | systemctl enable <service> |
| Disable | systemctl disable <service> |
Common service names: patroni, pgbouncer, haproxy, pg_exporter, pgbouncer_exporter, vip-manager
Patroni
Patroni is PostgreSQL’s HA manager, handling startup, shutdown, failure detection, and automatic failover. It’s the core PGSQL module component. PostgreSQL process is managed by Patroni - don’t use systemctl to manage postgres service directly.
Start Patroni
After starting, Patroni auto-launches PostgreSQL. On first start, behavior depends on role:
- Primary: Initialize or recover data directory
- Replica: Clone data from primary and establish replication
Stop Patroni
Stopping Patroni gracefully shuts down PostgreSQL. Note: If this is primary and auto-failover isn’t paused, may trigger failover.
Restart Patroni
Restart causes brief service interruption. For production, use pg restart for rolling restart.
Reload Patroni
Reload re-reads config file and applies hot-reloadable params to PostgreSQL.
View Status & Logs
Config file: /etc/patroni/patroni.yml
Best Practice: Use
patronictlinstead of systemctl to manage PostgreSQL clusters.
Pgbouncer
Pgbouncer is a lightweight PostgreSQL connection pooling middleware. Business traffic typically goes through Pgbouncer (6432) rather than directly to PostgreSQL (5432) for connection reuse and database protection.
Start Pgbouncer
Stop Pgbouncer
Note: Stopping Pgbouncer disconnects all pooled business connections.
Restart Pgbouncer
Restart disconnects all existing connections. For config changes only, use reload.
Reload Pgbouncer
Reload re-reads config files (user list, pool params, etc.) without disconnecting existing connections.
View Status & Logs
Config files:
- Main config:
/etc/pgbouncer/pgbouncer.ini - HBA rules:
/etc/pgbouncer/pgb_hba.conf - User list:
/etc/pgbouncer/userlist.txt - Database list:
/etc/pgbouncer/database.txt
Admin Console
Common admin commands:
HAProxy
HAProxy is a high-performance load balancer that routes traffic to correct PostgreSQL instances. Pigsty uses HAProxy to expose services, routing traffic based on role (primary/replica) and health status.
Start HAProxy
Stop HAProxy
Note: Stopping HAProxy disconnects all load-balanced connections.
Restart HAProxy
Reload HAProxy
HAProxy supports graceful reload without disconnecting existing connections. Use reload for config changes.
View Status & Logs
Config files: the main configuration is /etc/haproxy/haproxy.cfg; Pigsty-generated service fragments are stored under /etc/haproxy/conf.d/.
Admin Interface
HAProxy provides a web admin interface, default port 9101:
Default auth: username admin, password configured by haproxy_admin_password.
pg_exporter
pg_exporter is PostgreSQL’s Prometheus metrics exporter for collecting database performance metrics.
Start pg_exporter
Stop pg_exporter
After stopping, Prometheus can’t collect PostgreSQL metrics from this instance.
Restart pg_exporter
View Status & Logs
Config file: /etc/pg_exporter.yml
Verify Metrics
pgbouncer_exporter
pgbouncer_exporter is Pgbouncer’s Prometheus metrics exporter.
Start/Stop/Restart
View Status & Logs
Verify Metrics
vip-manager
vip-manager is an optional component for managing L2 VIP address floating.
When pg_vip_enabled is enabled, vip-manager binds VIP to current primary node.
Start vip-manager
Stop vip-manager
After stopping, VIP address is released from current node.
Restart vip-manager
View Status & Logs
Config file: /etc/default/vip-manager
Verify VIP Binding
Startup Order & Dependencies
Recommended PGSQL module component startup order:
Stop order should be reversed. Pigsty playbooks handle these dependencies automatically.
Batch Start All Services
Batch Stop All Services
Common Troubleshooting
Service Startup Failure
Patroni Won’t Start
| Symptom | Possible Cause | Solution |
|---|---|---|
| Can’t connect to etcd | etcd cluster unavailable | Check etcd service status |
| Data dir permission error | File ownership not postgres | chown -R postgres:postgres /pg/data |
| Port in use | Leftover PostgreSQL process | pg_ctl stop -D /pg/data or kill |
Pgbouncer Won’t Start
| Symptom | Possible Cause | Solution |
|---|---|---|
| Config syntax error | INI format error | Check /etc/pgbouncer/pgbouncer.ini |
| Port in use | Port 6432 already used | lsof -i :6432 |
| userlist.txt permissions | Incorrect file permissions | chmod 600 /etc/pgbouncer/userlist.txt |
HAProxy Won’t Start
| Symptom | Possible Cause | Solution |
|---|---|---|
| Config syntax error | Invalid main configuration or service fragment | haproxy -Ws -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d -c -q |
| Port in use | Service port conflict | lsof -i :5433 |
Related Documentation
- Patroni Management: Manage PostgreSQL HA with patronictl
- Cluster Management: Create, scale, destroy clusters
- Service Configuration: HAProxy service definition and config
- Monitoring System: PostgreSQL monitoring and alerting
8 - Manage PostgreSQL Cron Jobs
Pigsty uses crontab to manage scheduled tasks for routine backups, freezing aging transactions, and reorganizing bloated tables and indexes.
Quick Reference
| Operation | Quick Command | Description |
|---|---|---|
| Configure Cron Jobs | ./pgsql.yml -t pg_crontab -l <cls> |
Apply pg_crontab config |
| View Cron Jobs | crontab -l |
View as postgres user |
| Physical Backup | pg-backup [full|diff|incr] |
Execute backup with pgBackRest |
| Transaction Freeze | pg-vacuum [database...] |
Freeze aging transactions, prevent XID wraparound |
| Bloat Maintenance | pg-repack [database...] |
Online reorganize bloated tables and indexes |
For other management tasks, see: Backup Management, Monitoring System, HA Management.
Configure Cron Jobs
Use the pg_crontab parameter to configure cron jobs for the PostgreSQL database superuser (pg_dbsu, default postgres).
Example Configuration
The following pg-meta cluster configures a daily full backup at 1:00 AM, while pg-test configures weekly full backup on Monday with incremental backups on other days.
Recommended Maintenance Schedule
| Task | Frequency | Timing | Description |
|---|---|---|---|
pg-backup |
Daily | Early morning | Full or incremental backup, depending on business needs |
pg-vacuum |
Weekly | Sunday early morning | Freeze aging transactions, prevent XID wraparound |
pg-repack |
Weekly/Monthly | Off-peak hours | Reorganize bloated tables/indexes, reclaim space |
The pg-backup, pg-vacuum, and pg-repack scripts automatically detect the current node role. Only the primary will actually execute; replicas will exit directly. Therefore, you can safely configure the same cron jobs on all nodes, and after failover, the new primary will automatically continue executing maintenance tasks.
Apply Cron Jobs
Cron jobs are automatically written to the default location for the corresponding OS distribution when the pgsql.yml playbook executes (the pg_crontab task):
- EL (RHEL/Rocky/Alma):
/var/spool/cron/postgres - Debian/Ubuntu:
/var/spool/cron/crontabs/postgres
Each playbook execution will fully overwrite the cron job configuration.
View Cron Jobs
Execute the following command as the pg_dbsu OS user to view cron jobs:
If you’re not familiar with crontab syntax, refer to Crontab Guru for explanations.
pg-backup
pg-backup is Pigsty’s physical backup script based on pgBackRest, supporting full, differential, and incremental backup modes.
Basic Usage
Backup Types
| Type | Parameter | Description |
|---|---|---|
| Full Backup | full |
Complete backup of all data, only this backup needed for recovery |
| Differential | diff |
Backup changes since last full backup, recovery needs full + diff |
| Incremental | incr |
Backup changes since last any backup, recovery needs complete chain |
Execution Requirements
- Script must run on primary as postgres user
- Script auto-detects current node role, exits (exit 1) when run on replica
- Auto-retrieves stanza name from
/etc/pgbackrest/pgbackrest.conf
Common Cron Configurations
For more backup and recovery operations, see the Backup Management section.
pg-vacuum
pg-vacuum is Pigsty’s transaction freeze script for executing VACUUM FREEZE operations to prevent database shutdown from transaction ID (XID) wraparound.
Basic Usage
Command Options
| Option | Description | Default |
|---|---|---|
-h, --help |
Show help message | - |
-n, --dry-run |
Dry run mode, display only | false |
-a, --age |
Age threshold, tables exceeding need freeze | 100000000 |
-r, --ratio |
Aging ratio threshold, full freeze if exceeded (%) | 40 |
Logic
- Check database
datfrozenxidage, skip database if below threshold - Calculate aging page ratio (percentage of table pages exceeding age threshold of total pages)
- If aging ratio > 40%, execute full database
VACUUM FREEZE ANALYZE - Otherwise, only execute
VACUUM FREEZE ANALYZEon tables exceeding age threshold
Script sets vacuum_cost_limit = 10000 and vacuum_cost_delay = 1ms to control I/O impact.
Execution Requirements
- Script must run on primary as postgres user
- Uses file lock
/tmp/pg-vacuum.lockto prevent concurrent execution - Auto-skips
template0,template1,postgressystem databases
Common Cron Configuration
pg-repack
pg-repack is Pigsty’s bloat maintenance script based on the pg_repack extension for online reorganization of bloated tables and indexes.
Basic Usage
Command Options
| Option | Description | Default |
|---|---|---|
-h, --help |
Show help message | - |
-n, --dry-run |
Dry run mode, display only | false |
-t, --table |
Reorganize tables only | false |
-i, --index |
Reorganize indexes only | false |
-T, --timeout |
Lock wait timeout (seconds) | 10 |
-j, --jobs |
Parallel jobs | 2 |
Auto-Selection Thresholds
Script auto-selects objects to reorganize based on table/index size and bloat ratio:
Table Bloat Thresholds
| Size Range | Bloat Threshold | Max Count |
|---|---|---|
| < 256MB | > 40% | 64 |
| 256MB - 2GB | > 30% | 16 |
| 2GB - 8GB | > 20% | 4 |
| 8GB - 64GB | > 15% | 1 |
Index Bloat Thresholds
| Size Range | Bloat Threshold | Max Count |
|---|---|---|
| < 128MB | > 40% | 64 |
| 128MB - 1GB | > 35% | 16 |
| 1GB - 8GB | > 30% | 4 |
| 8GB - 64GB | > 20% | 1 |
Tables/indexes over 64GB are skipped with a warning and require manual handling.
Execution Requirements
- Script must run on primary as postgres user
- Requires
pg_repackextension installed (installed by default in Pigsty) - Requires
pg_table_bloatandpg_index_bloatviews inmonitorschema - Uses file lock
/tmp/pg-repack.lockto prevent concurrent execution - Auto-skips
template0,template1,postgressystem databases
Normal reads/writes are not affected during reorganization, but the final switch moment requires acquiring AccessExclusive lock on the table, blocking all access. For high-throughput workloads, recommend running during off-peak hours or maintenance windows.
Common Cron Configuration
You can confirm database bloat through Pigsty’s PGCAT Database - Table Bloat panel and select high-bloat tables and indexes for reorganization.
For more details see: Managing Relation Bloat
Remove Cron Jobs
When using the pgsql-rm.yml playbook to remove a PostgreSQL cluster, it automatically deletes the postgres user’s crontab file.
Related Documentation
- Backup Management: PostgreSQL backup and recovery
- Monitoring System: PostgreSQL monitoring and alerting
- Cluster Management: Cluster creation, scaling, and teardown
- Patroni Management: HA cluster management
9 - Managing PostgreSQL Extensions
Quick Start
Pigsty provides 575 extensions. Using extensions involves four steps: Download, Install, Configure, Enable.
For complete extension reference, see Extensions. For available extensions, see Extension Catalog.
| Action | Command | Description |
|---|---|---|
| Download Extensions | ./infra.yml -t repo_build |
Download extensions to local repo |
| Install Extensions | bin/pgsql-ext <cls> |
Install extension packages on cluster |
| Configure Extensions | pg edit-config <cls> -p |
Add to preload libs (requires restart) |
| Enable Extensions | psql -c 'CREATE EXT ...' |
Create extension objects in database |
| Update Extensions | ALTER EXTENSION UPDATE |
Update packages and extension objects |
| Remove Extensions | DROP EXTENSION |
Drop extension objects, uninstall pkgs |
Install Extensions
Extensions defined in pg_extensions are auto-installed during PostgreSQL cluster creation in the pg_extension task.
To install extensions on an existing cluster, add extensions to all.children.<cls>.pg_extensions, then execute:
Example: Install PostGIS, TimescaleDB and PGVector on cluster
Result: Installs extension packages on all cluster nodes. Pigsty auto-translates package aliases to actual package names for OS and PG version.
Before installing, ensure nodes have correct repos configured - extensions downloaded to local repo, or upstream repos configured.
Manual Install
If you don’t want to use Pigsty config to manage extensions, pass extension list directly on command line:
You can also use pig package manager CLI to install extensions on single node, with auto package alias resolution.
You can also use OS package manager directly (apt/dnf), but you must know the exact RPM/DEB package name for your OS/PG:
Download Extensions
To install extensions, ensure node’s extension repos contain the extension:
- Standalone install: No worries, upstream repos already added to node.
- Offline install: No worries, most extensions included in offline package, few require online install.
- Production multi-node deployment with local repo: depends - if extension was in
repo_packages/repo_extra_packageswhen creating local repo, it’s already downloaded. Otherwise download first or configure upstream repos for online install.
Pigsty’s default config auto-downloads mainstream extensions during installation. For additional extensions, add to repo_extra_packages and rebuild repo:
Configure Repos
You can also let all nodes use upstream repos directly (not recommended for production), skipping download and installing from upstream extension repos:
Configure Extensions
Some extensions require preloading to shared_preload_libraries, requiring database restart after modification.
Use pg_libs as its default value to configure preload extensions, but this only takes effect during cluster init - later modifications are ineffective.
For existing clusters, refer to Modify Config to modify shared_preload_libraries:
Ensure extension packages are correctly installed before adding preload config. If extension in shared_preload_libraries doesn’t exist or fails to load, PostgreSQL won’t start.
Also, manage cluster config changes through Patroni - avoid using ALTER SYSTEM or pg_parameters to modify instance config separately.
If primary and replica configs differ, it may cause startup failure or replication interruption.
Enable Extensions
After installing packages, execute CREATE EXTENSION in database to use extension features.
Enable during cluster init
Declare extensions to enable in database definition via extensions array:
Manual enable
Result: Creates extension objects (functions, types, operators, index methods, etc.) in database, enabling use of extension features.
Update Extensions
Extension updates involve two layers: package update and extension object update.
Update packages
Update extension objects
Backup database before updating extensions. Preloaded extensions may require PostgreSQL restart after update. Some extension version upgrades may be incompatible - check extension docs.
Remove Extensions
Removing extensions involves two layers: drop extension objects and uninstall packages.
Drop extension objects
Remove from preload
For preloaded extensions, remove from shared_preload_libraries and restart:
Uninstall packages (optional)
Using CASCADE to drop extensions also drops all objects depending on that extension (tables, indexes, views, etc.). Check dependencies before executing.
Query Extensions
Common SQL queries for extension info:
View enabled extensions
View available extensions
Check if extension is available
View extension dependencies
View extension objects
psql shortcuts
Add Repos
To install directly from upstream, manually add repos.
Using Pigsty playbook
YUM repos (EL systems)
APT repos (Debian/Ubuntu)
FAQ
Difference between extension name and package name
| Name | Description | Example |
|---|---|---|
| Extension name | Name used with CREATE EXTENSION |
vector |
| Package alias | Standardized name in Pigsty config | pgvector |
| Package name | Actual OS package name | pgvector_18* or postgresql-18-pgvector |
Preloaded extension prevents startup
If extension in shared_preload_libraries doesn’t exist or fails to load, PostgreSQL won’t start. Solutions:
- Ensure extension package is correctly installed
- Or remove extension from
shared_preload_libraries(edit/pg/data/postgresql.conf)
Extension dependencies
Some extensions depend on others, requiring sequential creation or using CASCADE:
Extension version incompatibility
View extension versions supported by current PostgreSQL:
Related Resources
- Extensions: Detailed extension management documentation
- Extension Catalog: Browse 575 available extensions
- pig Package Manager: Extension installation CLI tool
- Database Management: Enable extensions in databases
10 - Upgrading PostgreSQL Major/Minor Versions
Quick Start
PostgreSQL version upgrades fall into two types: minor version upgrade and major version upgrade, with very different risk and complexity.
| Type | Example | Downtime | Data Compatibility | Risk |
|---|---|---|---|---|
| Minor upgrade | 17.2 → 17.3 | Seconds (rolling) | Fully compatible | Low |
| Major upgrade | 17 → 18 | Minutes | Requires data dir upgrade | Medium |
For detailed online migration process, see Online Migration documentation.
| Action | Description | Risk |
|---|---|---|
| Minor Version Upgrade | Update packages, rolling restart | Low |
| Minor Version Downgrade | Rollback to previous minor version | Low |
| Major Version Upgrade | Logical replication or pg_upgrade | Medium |
| Extension Upgrade | Upgrade extension packages and objects | Low |
Minor Version Upgrade
Minor version upgrades (e.g., 17.2 → 17.3) are the most common upgrade scenario, typically for security patches and bug fixes. Data directory is fully compatible, completed via rolling restart.
Strategy: Recommended rolling upgrade: upgrade replicas first, then switchover to upgrade original primary - minimizes service interruption.
Step 1: Prepare packages
Ensure local repo has latest PostgreSQL packages and refresh node cache:
Step 2: Upgrade replicas
Upgrade packages on all replicas and verify version:
Restart all replicas to apply new version:
Step 3: Switchover
Execute switchover to transfer primary role to upgraded replica:
Step 4: Upgrade original primary
Original primary is now replica - upgrade packages and restart:
Step 5: Verify
Confirm all instances have consistent version:
Minor Version Downgrade
In rare cases (e.g., new version introduces bugs), may need to downgrade PostgreSQL to previous version.
Step 1: Get old version packages
Step 2: Execute downgrade
Step 3: Restart cluster
Major Version Upgrade
Major version upgrades (e.g., 17 → 18) involve data format changes, requiring specialized tools for data migration.
| Method | Downtime | Complexity | Use Case |
|---|---|---|---|
| Logical Replication Migration | Seconds (switch) | High | Production, minimal downtime required |
| pg_upgrade In-Place Upgrade | Minutes~Hours | Medium | Test env, smaller data |
For production, we recommend logical replication migration: create new version cluster, sync data via logical replication, then blue-green switch. Shortest downtime and rollback-ready. See Online Migration.
Logical Replication Migration
Logical replication is the recommended approach for production major version upgrades. Core steps:
Step 1: Create new version cluster
Step 2: Configure logical replication
Step 3: Wait for sync completion
Step 4: Switch traffic
After confirming data sync complete: stop app writes to source → wait for final sync → switch app connections to new cluster → drop subscription, decommission source.
For detailed migration process, see Online Migration documentation.
pg_upgrade In-Place Upgrade
pg_upgrade is PostgreSQL’s official major version upgrade tool, suitable for test environments or scenarios accepting longer downtime.
In-place upgrade causes longer downtime and is difficult to rollback. For production, prefer logical replication migration.
Step 1: Install new version packages
Step 2: Stop Patroni
Step 3: Run pg_upgrade
Step 4: Update links and start
Step 5: Post-processing
Extension Upgrade
When upgrading PostgreSQL version, typically also need to upgrade related extensions.
Upgrade extension packages
Upgrade extension objects
After package upgrade, execute extension upgrade in database:
Before major version upgrade, confirm all extensions support target PostgreSQL version. Some extensions may require uninstall/reinstall - check extension documentation.
Important Notes
- Backup first: Always perform complete backup before any upgrade
- Test verify: Verify upgrade process in test environment first
- Extension compatibility: Confirm all extensions support target version
- Rollback plan: Prepare rollback plan, especially for major upgrades
- Monitor closely: Monitor database performance and error logs after upgrade
- Document: Record all operations and issues during upgrade
Related Documentation
- Online Migration: Zero-downtime migration using logical replication
- Patroni Management: Manage cluster with patronictl
- Cluster Management: Cluster creation, scaling, destruction
- Backup Recovery: PostgreSQL backup and recovery
- Extension Management: Extension installation and management