TABLE OF CONTENTS
- •How well does your PostgreSQL follow these practices?
- •At a Glance: 10 Core Rules for PostgreSQL
- •1. Stay on a Supported Version
- •2. Backups: A Backup You Cannot Restore Is Not a Backup
- •3. High Availability: Automate Failover
- •4. Use a Connection Pooler
- •5. Size Memory and Checkpoint Settings
- •6. Tune the Operating System for the Database
- •7. Security: Least Privilege, SCRAM and TLS
- •8. Never Turn Off Autovacuum; Tune It
- •9. Continuous Monitoring
- •10. Design the Schema Right from the Start
- •Quick Self-Assessment
- •PostgreSQL with Aryasoft
- •Frequently Asked Questions
- •Sources
- •Let’s review your PostgreSQL environment together
PostgreSQL best practices are the core rules for running a database safely, fast and sustainably in production. The most important are: tested backups with point-in-time recovery (PITR), high availability with automatic failover, a connection pooler, settings sized to memory, least privilege and encrypted connections, autovacuum that runs regularly, continuous monitoring and staying on a supported version.
This guide is for teams running PostgreSQL in production or preparing to. We grouped the recommendations under ten headings and answered the “why” for each one. The details are based on the PostgreSQL 18 documentation, and we ran every query on PostgreSQL 18.
How well does your PostgreSQL follow these practices?
Aryasoft's senior PostgreSQL experts review configuration, backups, high availability, security and performance, and report findings in priority order.
At a Glance: 10 Core Rules for PostgreSQL
| # | Rule | What happens if you skip it? |
|---|---|---|
| 1 | Run a supported version and the latest minor release. | Known security holes and bugs stay unfixed. |
| 2 | Set up backups with WAL archiving and test restores. | Data cannot be recovered after a logical error or failure. |
| 3 | Build high availability with automatic failover. | A server failure lasts as long as manual intervention takes. |
| 4 | Put a connection pooler between the application and the database. | As connections grow, memory runs out and performance drops. |
| 5 | Size memory and checkpoint settings for the hardware. | The default settings use only a small part of the server’s capacity. |
| 6 | Tune the operating system for the database. | Unexpected shutdowns and stalls caused by memory management. |
| 7 | Use least privilege, SCRAM and TLS. | A single leaked password can expose all the data. |
| 8 | Never turn off autovacuum; tune it on busy tables. | Tables bloat, queries slow down and, in the worst case, the database stops accepting writes. |
| 9 | Monitor queries, replication and capacity continuously. | Problems are noticed only when users complain. |
| 10 | Design the schema right from the start. | Tables without primary keys, wrong data types and missing indexes are expensive to fix later. |
1. Stay on a Supported Version
The PostgreSQL community supports each major version for five years and releases minor versions at least every three months. Minor releases contain only bug and security fixes; they need no dump or pg_upgrade and are usually applied by updating the packages and restarting the service. The community recommends always running the latest minor release.
| Situation | Recommendation |
|---|---|
| New installation | PostgreSQL 18 (supported until November 2030) |
| Running PostgreSQL 14 | Support ends November 12, 2026; plan the upgrade now. |
| Minor updates | On a quarterly schedule, test environment first |
| Major upgrades | Planned at least six months before end of support |
We cover target version and method selection for leaving PostgreSQL 14 in detail in our PostgreSQL 14 end of life guide.
2. Backups: A Backup You Cannot Restore Is Not a Backup
PostgreSQL offers three backup approaches, and they complement rather than replace each other:
| Method | What it gives you | Limitation |
|---|---|---|
| pg_dump (logical backup) | A portable copy of a single database or table; can be restored to a different version. | No point-in-time recovery; slow on large databases. |
| Base backup + WAL archive (physical) | A copy of the whole cluster and recovery to any given second (PITR) | Restores only to the same major version. |
| Replication | A ready copy that protects against hardware failure | Not a backup: data deleted by mistake is deleted on the replica too. |
For production we recommend physical backups with continuous WAL archiving using a tool such as pgBackRest. Backups should be kept off the database server, preferably in a different location, and at least one copy should be on immutable storage as protection against ransomware.
Critical
A backup setup that has never been restored is only an assumption. Test a restore at least every three months, to a separate server and to a specific point in time; time it and compare the result with your RTO target.
3. High Availability: Automate Failover
PostgreSQL supports standby servers with streaming replication out of the box. It does not, however, include a mechanism that detects a failed primary and promotes a replica automatically. The common solution is Patroni, together with a distributed configuration store such as etcd that it uses to make decisions.
- Plan for at least three servers: a primary, a replica and an odd number of members for the decision layer (etcd). Three etcd members survive one failure, five survive two.
- Define your tolerance for data loss: with asynchronous replication the last transactions can be lost at failover. If that is unacceptable, use synchronous replication.
- Keep the connection address stable: applications should connect to a virtual IP, a load balancer or a DNS name, not to a server address.
- Test failover: before go-live and at regular intervals afterwards.
We use Autobase to install these components consistently. We describe what we watch for in our article on building a high-availability PostgreSQL environment with Autobase.
4. Use a Connection Pooler
PostgreSQL opens a separate operating system process for each connection. As connections grow, memory use and context-switching costs grow with them. For applications that open hundreds or thousands of concurrent connections, raising max_connections is not the answer; a connection pooler such as PgBouncer is.
| Pool mode | How it works | When to use it |
|---|---|---|
| Session | The client holds a database connection for the whole session. | The most compatible option; applications that use session-level features |
| Transaction | A connection is given to the client only for the duration of a transaction. | Many clients running short transactions; the most efficient option |
Idle connections that the application never closes are another common problem. Sessions that start a transaction and then wait without finishing it in particular block VACUUM. Close them after a set time with idle_in_transaction_session_timeout.
-- Sessions by state, and the oldest open transaction
SELECT state, count(*) AS sessions,
max(now() - xact_start) AS oldest_transaction
FROM pg_stat_activity
WHERE backend_type = 'client backend'
GROUP BY state
ORDER BY sessions DESC;
5. Size Memory and Checkpoint Settings
PostgreSQL’s defaults are chosen conservatively so it can run on a small machine. These are the first settings to review on a production server:
| Setting | Default | Starting point | Notes |
|---|---|---|---|
shared_buffers |
128 MB | 25% of RAM | PostgreSQL’s data page cache. The documentation suggests 25% as a starting point for dedicated database servers. |
effective_cache_size |
4 GB | 50–75% of RAM | Allocates no memory; tells the query planner how large the operating system cache is. |
work_mem |
4 MB | Depends on the workload | Used separately by every sort and hash operation; think of it multiplied by the connection count. |
maintenance_work_mem |
64 MB | 512 MB – 1 GB | Speeds up maintenance such as VACUUM and CREATE INDEX. |
max_wal_size |
1 GB | Raised for the write load | Too small means frequent checkpoints and lower write performance. |
checkpoint_completion_target |
0.9 | 0.9 | Spreads checkpoint writes over time. |
work_mem is the parameter that needs the most care. A value of 64 MB, for example, can be used several times by one complex query, and multiplied by hundreds of connections it can exceed the server’s memory. It is safer to keep it low globally and raise it per session or per role for heavy reporting queries.
6. Tune the Operating System for the Database
| Setting | Recommendation | Why? |
|---|---|---|
| Memory overcommit | vm.overcommit_memory = 2 |
The PostgreSQL documentation recommends it to reduce the risk of Linux killing the database process (OOM killer) when memory runs out. |
| Transparent Huge Pages | Off | Can cause unexpected stalls in memory management. |
| Huge pages | huge_pages = try and pages reserved in the OS |
Reduces memory management overhead with large shared_buffers values. |
| Swap usage | Low vm.swappiness (for example 1) |
Keeps database memory from being moved to disk. |
| Time sync | NTP (chrony) on | Logs, replication and cluster management depend on correct time. |
| Disk | SSD/NVMe; data and backups on separate disks | Latency feeds straight into query time; backups on the same disk are lost with it. |
7. Security: Least Privilege, SCRAM and TLS
- Do not give applications superuser rights. Each application should connect with its own role and hold only the privileges it needs in its own database. Use the
postgresrole for administration only. - Store passwords with SCRAM-SHA-256. MD5 password support was deprecated in PostgreSQL 18; find roles using MD5 and reset their passwords.
- Keep
pg_hba.confrules narrow. Name a specific database, role and network in every rule; never use thetrustmethod for network connections. - Encrypt connections. Use
hostsslfor remote connections and set the minimum TLS version to 1.2. - Keep the database off the internet. Port 5432 should be open only to application servers.
- Record privileged activity. Log connections, disconnections and DDL; consider the pgAudit extension for audit requirements.
-- Roles with superuser or other elevated attributes
SELECT rolname, rolsuper, rolcreaterole, rolcreatedb, rolreplication, rolbypassrls
FROM pg_roles
WHERE rolsuper OR rolcreaterole OR rolreplication OR rolbypassrls
ORDER BY rolname;
-- Roles still using MD5 password hashes
SELECT rolname FROM pg_authid WHERE rolpassword LIKE 'md5%';
8. Never Turn Off Autovacuum; Tune It
PostgreSQL does not delete old versions of updated and deleted rows immediately. Autovacuum cleans up these “dead rows”. It also updates the query planner’s statistics and prevents transaction ID wraparound. Turning autovacuum off may look like a quick performance win, but in the medium term it leads to bloated tables and, in the worst case, a database that refuses new transactions.
On large, heavily updated tables the default thresholds can kick in too late. Tune autovacuum per table to run more often on those tables, and watch these two queries regularly:
-- Tables with the most dead rows and their last autovacuum
SELECT relname, n_live_tup, n_dead_tup, last_autovacuum, last_autoanalyze
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 10;
-- Transaction ID age per database (autovacuum_freeze_max_age default: 200 million)
SELECT datname, age(datfrozenxid) AS xid_age
FROM pg_database
ORDER BY xid_age DESC;
Warning
Long-running transactions, replication slots and prepared transactions all stop VACUUM from cleaning up old rows. If transaction ID age keeps rising, check these three sources first.
9. Continuous Monitoring
Good monitoring shows problems before users notice them. Define alerts for at least these metrics:
| Metric | Source | Why it matters |
|---|---|---|
| Most expensive queries | pg_stat_statements |
Where performance tuning pays off fastest |
| Replication lag | pg_stat_replication |
Determines possible data loss at failover and read consistency |
| Connection count and idle transactions | pg_stat_activity |
Reveals connection leaks and VACUUM blockers |
| Transaction ID age | pg_database |
Warns of wraparound risk early |
| Disk usage and WAL build-up | Operating system, pg_replication_slots |
A forgotten slot can fill the disk |
| Backup and archiving success | Backup tool, pg_stat_archiver |
Failed archiving silently removes your ability to do PITR |
The pg_stat_statements extension is the foundation of query-level performance analysis. It becomes available once it is added to shared_preload_libraries and the server is restarted:
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
-- Top 10 queries by total execution time
SELECT round(total_exec_time::numeric, 0) AS total_ms,
calls,
round(mean_exec_time::numeric, 1) AS mean_ms,
left(query, 80) AS query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
To see slow queries in the server log as well, turn on log_min_duration_statement (for example 1 second), log_lock_waits for lock waits and log_checkpoints for checkpoint behavior.
10. Design the Schema Right from the Start
| Rule | Why? |
|---|---|
| Give every table a primary key. | Logical replication, many tools and data integrity depend on it. |
Use GENERATED ... AS IDENTITY for auto-increment keys. |
It follows the SQL standard and avoids the ownership and permission quirks of serial. |
Store time with timestamptz. |
Prevents errors caused by time zone differences. |
Use numeric for money and exact numbers. |
Floating-point types produce rounding errors. |
| Index foreign key columns. | PostgreSQL does not create these indexes automatically; deletes and joins slow down. |
| Choose the locale on day one for language-specific data. | A database’s locale cannot be changed later. |
| Write object names in lower case without quotes. | Quoted names become case-sensitive and cause errors in queries. |
Tip
For languages with special case rules, such as Turkish with its dotted and dotless i, use an ICU collation for that language to get correct case conversion and alphabetical order. You will find examples in our What Is PostgreSQL? guide.
Quick Self-Assessment
If you can answer “yes” to each of these questions, your PostgreSQL environment stands on solid foundations:
- Is a supported major version with the latest minor release running?
- Has a restore to a separate server been tested in the last three months?
- When the primary goes down, does a replica take over without anyone stepping in?
- Do applications connect through a connection pooler?
- Are
shared_buffersandwork_memset for the server’s memory? - Does no application connect with superuser rights?
- Are all remote connections encrypted?
- Is autovacuum on and is transaction ID age monitored?
- Are there alerts for replication lag, disk usage and backup success?
- Does every table have a primary key?
PostgreSQL with Aryasoft
Aryasoft’s senior-only team offers the services it provides for SQL Server for PostgreSQL as well: health checks, architecture and installation, high availability and backup design, performance tuning, version upgrades and migrations from SQL Server or Oracle to PostgreSQL. A health check shows how far the rules in this guide are applied in your environment, and we report the findings in priority order. For ongoing support, see our managed database services, which include a remote DBA service.
Frequently Asked Questions
Sources
The details in this guide were checked against the official documentation below in November 2026.
- PostgreSQL: Versioning Policy
- PostgreSQL documentation: Backup and Restore
- PostgreSQL documentation: Continuous Archiving and Point-in-Time Recovery
- PostgreSQL documentation: High Availability, Load Balancing, and Replication
- PostgreSQL documentation: Resource Consumption
- PostgreSQL documentation: Write Ahead Log
- PostgreSQL documentation: Query Planning (effective_cache_size)
- PostgreSQL documentation: Managing Kernel Resources (overcommit, huge pages)
- PostgreSQL documentation: Password Authentication
- PostgreSQL documentation: The pg_hba.conf File
- PostgreSQL documentation: Routine Vacuuming
- PostgreSQL documentation: The Cumulative Statistics System
- PostgreSQL documentation: pg_stat_statements
- PostgreSQL documentation: Client Connection Defaults (idle_in_transaction_session_timeout)
- PostgreSQL documentation: Identity Columns
- PgBouncer: Features
- Patroni documentation
PostgreSQL Health Check
Let’s review your PostgreSQL environment together
Aryasoft’s senior PostgreSQL experts review configuration, backups, high availability, security and performance and report findings in priority order.