PostgreSQL in Production: A Practical Checklist
10 min read
PostgreSQL in Production: A Practical Checklist
Getting Postgres running locally is straightforward. Running it reliably in production requires attention to configuration, backups, observability, and security. This lesson covers the practical checklist that CPCODELAB follows on every project.
Connection & Security
- Never use the
postgressuperuser from application code. Create a dedicated application role with the minimum necessary privileges. - Restrict
pg_hba.confto only allow connections from known IP ranges. Disable remote connections for the superuser. - Use SSL/TLS for all connections (
?sslmode=requirein the connection string). - Store credentials in environment variables or a secrets manager — never in code.
- Enable
log_connectionsandlog_disconnectionsso you can audit who is connecting.
sql
-- Create a limited application role
CREATE ROLE app_user LOGIN PASSWORD 'a-very-strong-password';
GRANT CONNECT ON DATABASE cpcode_app TO app_user;
GRANT USAGE ON SCHEMA public TO app_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app_user;
-- For future tables
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_user;Backups
- pg_dump — logical backup of a single database. Portable and human-readable.
- pg_basebackup — physical backup of the entire cluster. Required for PITR.
- WAL archiving + PITR — stream WAL files to object storage for point-in-time recovery. The gold standard for production.
- Test restores regularly — a backup you have never tested is not a backup.
- Managed services like Neon, Supabase, and RDS handle backups automatically.
bash
# Create a compressed logical backup
pg_dump -U myuser -d cpcode_app -Fc -f backup.dump
# Restore from a pg_dump backup
pg_restore -U myuser -d cpcode_app_restore -Fc backup.dumpObservability & Tuning
- Enable
pg_stat_statementsto track the slowest queries over time. - Set
log_min_duration_statement = 1000to log queries slower than 1 second. - Monitor replication lag if you use read replicas.
- Set
work_mem,shared_buffers, andeffective_cache_sizebased on your server RAM. - Run
VACUUMregularly (autovacuum is on by default; tune its thresholds for high-write tables). - Use
pg_activityorpgBadgerfor real-time and historic query analysis.
sql
-- Enable pg_stat_statements (add to postgresql.conf: shared_preload_libraries = 'pg_stat_statements')
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
-- Find the slowest queries
SELECT
round(total_exec_time::numeric, 2) AS total_ms,
calls,
round(mean_exec_time::numeric, 2) AS mean_ms,
left(query, 120) AS query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;At CPCODELAB every production Postgres instance runs on a managed platform (Neon or Supabase) so that backups, replication, and patching are handled for us. We focus on schema design and query performance rather than infrastructure.
Ready to test yourself?
Practice PostgreSQL— quiz & coding exercises