Checklists / PostgreSQL

The PostgreSQL production and performance checklist.

38 checks across configuration, backups and recovery, monitoring, indexes and queries, autovacuum and bloat, connections and pooling, security, high availability and upgrades. Tick items off as you go. Your progress is saved in this browser.

0 of 38 complete

1. Configuration

2. Backups and recovery

3. Monitoring

Top 10 queries by total time (PostgreSQL 13+)

SELECT calls,
       round(total_exec_time::numeric, 0) AS total_ms,
       round(mean_exec_time::numeric, 2)  AS mean_ms,
       left(query, 80)                    AS query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;

4. Indexes and queries

Indexes that have never been used since the last stats reset

SELECT schemaname, relname, indexrelname, idx_scan,
       pg_size_pretty(pg_relation_size(indexrelid)) AS size
FROM pg_stat_user_indexes
WHERE idx_scan = 0
ORDER BY pg_relation_size(indexrelid) DESC
LIMIT 20;

5. Autovacuum and bloat

Tables with the most dead tuples, and transaction ID age per database

SELECT relname, n_live_tup, n_dead_tup, last_autovacuum
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 10;

SELECT datname, age(datfrozenxid) AS xid_age
FROM pg_database
ORDER BY xid_age DESC;

6. Connections and pooling

7. Security

8. High availability and upgrades

Want this done for you?

I run a fixed-price PostgreSQL performance audit: slow query analysis, indexing, autovacuum, and connection pooling, on RDS, Cloud SQL, Supabase, or self-hosted. You get a written report with a prioritized fix list and expected impact, delivered in one week.

Frequently asked questions

What should shared_buffers be set to?

A common starting point on a dedicated database server is about 25% of RAM. Measure with your real workload before going much higher, because PostgreSQL also relies on the operating system's file cache.

How do I find slow queries in PostgreSQL?

Enable the pg_stat_statements extension and sort by total execution time to see which queries cost the most overall. Then run EXPLAIN (ANALYZE, BUFFERS) on the top ones. Setting log_min_duration_statement also captures individual slow executions in the log.

How do I know if autovacuum is keeping up?

Check n_dead_tup and last_autovacuum in pg_stat_user_tables. Tables with a large dead-to-live ratio and an old last_autovacuum are falling behind. Also monitor transaction ID age with age(datfrozenxid) in pg_database.

Do I need PgBouncer?

If your application opens many short-lived connections, or you run many application instances, a pooler usually helps. Each PostgreSQL connection is a process, so thousands of direct connections hurt performance even when most are idle.

How often should I test restoring my PostgreSQL backups?

At least quarterly, and after any change to the backup setup. Time the restore so you know your real recovery time, not the one you assume.

What is asynchronous I/O in PostgreSQL 18?

PostgreSQL 18 added an asynchronous I/O subsystem so backends can start several reads and keep working while they complete, instead of waiting on each one. It is controlled by io_method (worker, io_uring, or sync) and currently speeds up reads such as sequential scans, bitmap heap scans, and vacuum. Gains depend on your storage and workload, so measure on your own data.

What is pg_squeeze and when should I use it?

pg_squeeze is an extension that removes bloat from tables by rewriting them in the background, holding an exclusive lock only briefly at the end. Use it when VACUUM can't shrink a table and VACUUM FULL's long lock is unacceptable. It requires shared_preload_libraries, wal_level = logical (before PostgreSQL 19), and a primary key or a unique index set as the replica identity.

Related