# PostgreSQL Production Configuration # Custom PHP Framework - Production Optimized Settings # PostgreSQL 16 # ============================================================================ # CONNECTIONS AND AUTHENTICATION # ============================================================================ # Maximum number of concurrent connections max_connections = 100 # Reserved connections for superuser emergency access superuser_reserved_connections = 3 # ============================================================================ # MEMORY CONFIGURATION # ============================================================================ # Shared memory for cache (25% of RAM, adjust based on available memory) # For 4GB RAM server: 1GB # For 8GB RAM server: 2GB # For 16GB RAM server: 4GB shared_buffers = 2GB # Memory for complex sorts (per operation) work_mem = 16MB # Memory for maintenance operations (VACUUM, CREATE INDEX) maintenance_work_mem = 256MB # Maximum memory for autovacuum workers autovacuum_work_mem = 128MB # Effective cache size (hint for query planner, 50-75% of RAM) effective_cache_size = 6GB # ============================================================================ # WRITE-AHEAD LOG (WAL) # ============================================================================ # WAL level for replication and point-in-time recovery wal_level = replica # Minimum size of past WAL files min_wal_size = 1GB # Maximum size of WAL files max_wal_size = 4GB # Number of WAL sender processes (for replication) max_wal_senders = 3 # Number of replication slots max_replication_slots = 3 # WAL keep size (for replication lag) wal_keep_size = 1GB # Synchronous commit (trade-off between durability and performance) # on: Full durability (safest, slower) # remote_apply: Wait for replica to apply (if using streaming replication) # local: Wait for local flush (balanced) # off: Fastest but risk of data loss on crash (NOT recommended for production) synchronous_commit = on # Checkpoint frequency (time between checkpoints) checkpoint_timeout = 15min # Target checkpoint completion time (fraction of checkpoint_timeout) checkpoint_completion_target = 0.9 # ============================================================================ # QUERY PLANNING # ============================================================================ # Random page cost (lower for SSD, higher for HDD) # SSD: 1.0-1.1, HDD: 4.0 random_page_cost = 1.1 # Sequential page cost seq_page_cost = 1.0 # Effective I/O concurrency (number of concurrent disk I/O operations) # SSD: 200, HDD: 2-4 effective_io_concurrency = 200 # ============================================================================ # PARALLELISM # ============================================================================ # Maximum number of parallel workers per query max_parallel_workers_per_gather = 2 # Maximum number of parallel maintenance workers max_parallel_maintenance_workers = 2 # Maximum number of parallel workers (total across all sessions) max_parallel_workers = 4 # ============================================================================ # LOGGING # ============================================================================ # Log destination log_destination = 'stderr' # Logging collector (rotate logs automatically) logging_collector = on # Log directory log_directory = 'log' # Log filename pattern (include date for rotation) log_filename = 'postgresql-%Y-%m-%d.log' # Log rotation age (daily) log_rotation_age = 1d # Log rotation size (500MB per file) log_rotation_size = 500MB # Truncate logs on rotation log_truncate_on_rotation = on # Log line prefix (include timestamp, user, database, PID) log_line_prefix = '%t [%p] %u@%d ' # Log connections log_connections = on # Log disconnections log_disconnections = on # Log duration of statements (in milliseconds) # Log only slow queries (>500ms) log_min_duration_statement = 500 # Log lock waits (statements waiting for locks) log_lock_waits = on # Log checkpoints log_checkpoints = on # Log autovacuum activity log_autovacuum_min_duration = 0 # ============================================================================ # AUTOVACUUM # ============================================================================ # Enable autovacuum autovacuum = on # Maximum number of autovacuum workers autovacuum_max_workers = 3 # Naptime between autovacuum runs autovacuum_naptime = 1min # Minimum number of updated/deleted tuples before vacuum autovacuum_vacuum_threshold = 50 # Minimum number of inserted tuples before analyze autovacuum_analyze_threshold = 50 # Fraction of table size to add to vacuum threshold autovacuum_vacuum_scale_factor = 0.1 # Fraction of table size to add to analyze threshold autovacuum_analyze_scale_factor = 0.05 # Cost delay for autovacuum (throttling) autovacuum_vacuum_cost_delay = 10ms # Cost limit for autovacuum autovacuum_vacuum_cost_limit = 200 # ============================================================================ # STATISTICS # ============================================================================ # Track activity across all databases track_activities = on # Track counts of rows accessed track_counts = on # Track I/O timing track_io_timing = on # Track functions track_functions = all # ============================================================================ # CONNECTION POOLING SUPPORT # ============================================================================ # Prepared statements (use with PgBouncer in transaction pooling mode) # For PgBouncer: set to 'auto' or create prepared statements per transaction # For direct connections: 'on' for better performance # plan_cache_mode = auto # ============================================================================ # STATEMENT TIMEOUT # ============================================================================ # Maximum statement execution time (30 seconds) # Prevents long-running queries from blocking statement_timeout = 30s # Lock timeout (10 seconds) # Prevents long lock waits lock_timeout = 10s # Idle in transaction session timeout (5 minutes) # Closes idle transactions automatically idle_in_transaction_session_timeout = 5min # ============================================================================ # SECURITY # ============================================================================ # SSL configuration (if using SSL) # ssl = on # ssl_cert_file = '/path/to/server.crt' # ssl_key_file = '/path/to/server.key' # ssl_ca_file = '/path/to/ca.crt' # Password encryption (scram-sha-256 is most secure) password_encryption = scram-sha-256 # ============================================================================ # CLIENT CONNECTION DEFAULTS # ============================================================================ # Default transaction isolation level default_transaction_isolation = 'read committed' # Timezone timezone = 'UTC' # Client encoding client_encoding = 'UTF8' # Locale settings lc_messages = 'en_US.UTF-8' lc_monetary = 'en_US.UTF-8' lc_numeric = 'en_US.UTF-8' lc_time = 'en_US.UTF-8' # Default text search configuration default_text_search_config = 'pg_catalog.english' # ============================================================================ # PERFORMANCE TUNING NOTES # ============================================================================ # These settings are optimized for: # - 8GB RAM server # - SSD storage # - Mixed OLTP/OLAP workload # - Connection pooling via PgBouncer (optional) # Adjust based on your hardware: # # For 4GB RAM server: # shared_buffers = 1GB # effective_cache_size = 3GB # work_mem = 8MB # # For 16GB RAM server: # shared_buffers = 4GB # effective_cache_size = 12GB # work_mem = 32MB # # For HDD storage: # random_page_cost = 4.0 # effective_io_concurrency = 2 # ============================================================================ # MONITORING QUERIES # ============================================================================ # Check current connections: # SELECT count(*) FROM pg_stat_activity; # Check slow queries: # SELECT pid, query, now() - query_start AS duration # FROM pg_stat_activity # WHERE state = 'active' AND now() - query_start > interval '5 seconds'; # Check database size: # SELECT pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) # FROM pg_database ORDER BY pg_database_size(pg_database.datname) DESC; # Check table bloat (vacuum needed): # SELECT schemaname, tablename, # pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size # FROM pg_tables WHERE schemaname = 'public' ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC; # Check index usage: # SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read, idx_tup_fetch # FROM pg_stat_user_indexes ORDER BY idx_scan ASC;