}

PostgreSQL Configuration Tuning

Introduction

PostgreSQL is a powerful open-source relational database, but its default configuration is intentionally conservative to run on minimal hardware. To get the best performance for your workload, you need to tune several key parameters in the postgresql.conf file.

This guide covers the most important PostgreSQL configuration settings and how to calculate optimal values based on your server's available RAM and workload type.

Memory Settings

Memory configuration is the most impactful area for PostgreSQL performance. Here are the key parameters:

shared_buffers

This is PostgreSQL's dedicated memory cache for table and index data. It's the most important memory setting.

Recommended value: 25% of total system RAM (but no more than 8GB on most systems)

# For a server with 16GB RAM:
shared_buffers = 4GB

Start with 25% of RAM. On systems with very large amounts of RAM (64GB+), you may cap this at 8-16GB since the operating system's file cache also helps.

work_mem

Memory used for internal sort operations and hash tables before writing to temporary disk files. Each query can use multiple work_mem buffers, so be careful not to set this too high.

Recommended value: Total RAM / max_connections / 4

# For a server with 16GB RAM and 100 connections:
work_mem = 40MB

For OLAP workloads with complex queries and few connections, you can increase this significantly. For OLTP with many concurrent connections, keep it lower.

maintenance_work_mem

Memory for maintenance operations like VACUUM, CREATE INDEX, and ALTER TABLE ADD FOREIGN KEY.

Recommended value: 5-10% of RAM (up to 1-2GB)

maintenance_work_mem = 1GB

Since these operations typically run one at a time, you can set this higher than work_mem.

effective_cache_size

This doesn't allocate memory; it tells the query planner how much memory is available for caching (PostgreSQL buffers + OS file cache). Helps the planner decide whether to use index scans.

Recommended value: 50-75% of total system RAM

# For a server with 16GB RAM:
effective_cache_size = 12GB

Connection Settings

max_connections

Maximum number of concurrent connections to the database. Each connection consumes memory even when idle.

Recommended value: Only as many as you actually need

max_connections = 100

Rather than increasing this to thousands, use a connection pooler like PgBouncer. A good rule of thumb: set this to 2-3x your CPU cores for CPU-bound workloads.

WAL Settings

Write-Ahead Logging (WAL) settings affect write performance and crash recovery.

wal_buffers

Shared memory for WAL data that hasn't been written to disk yet.

Recommended value: 3% of shared_buffers (up to 64MB)

wal_buffers = 64MB

PostgreSQL 9.1+ auto-tunes this, but you can set it explicitly.

checkpoint_completion_target

Spreads checkpoint I/O over a longer period to reduce disk spikes.

Recommended value: 0.9

checkpoint_completion_target = 0.9

max_wal_size

Maximum size of WAL files between automatic checkpoints. Higher values reduce checkpoint frequency but increase recovery time.

Recommended value: 1GB-4GB depending on write load

max_wal_size = 2GB
min_wal_size = 1GB

Quick Configuration by RAM Size

Here's a quick reference for common server sizes:

4GB RAM Server:

shared_buffers = 1GB
effective_cache_size = 3GB
maintenance_work_mem = 256MB
work_mem = 10MB

16GB RAM Server:

shared_buffers = 4GB
effective_cache_size = 12GB
maintenance_work_mem = 1GB
work_mem = 40MB

64GB RAM Server:

shared_buffers = 16GB
effective_cache_size = 48GB
maintenance_work_mem = 2GB
work_mem = 160MB

Applying Changes

After modifying postgresql.conf, some settings require a restart while others only need a reload:

# Reload configuration (for most settings):
sudo systemctl reload postgresql

# Restart (required for shared_buffers, max_connections):
sudo systemctl restart postgresql

Check current values with:

SHOW shared_buffers;
SHOW work_mem;
-- Or view all settings:
SELECT name, setting, unit FROM pg_settings WHERE name IN ('shared_buffers', 'work_mem', 'effective_cache_size');

Conclusion

PostgreSQL tuning isn't one-size-fits-all. Start with these recommendations based on your RAM, then monitor performance using tools like pg_stat_statements and EXPLAIN ANALYZE. Adjust based on your actual workload—OLTP applications need different settings than data warehouses.

For automated tuning suggestions, check out PGTune which generates configuration based on your hardware specs.