Skip to main content
This guide covers common monitoring scenarios with ready-to-use SQL queries. Each section starts with the question you’re trying to answer, then provides the query.

Find slow queries

Top queries by tail latency

Use the pre-aggregated query_stats_5m view to find the worst p99 latencies without scanning raw events:

Latency trend for a specific query

After identifying a slow query_id, see how its performance changes over time. This is something pg_stat_statements cannot do since it only stores cumulative counters.

Individual slow executions

Find the specific query executions that were slowest:

Diagnose cache problems

Cache miss outliers

Find individual executions with the most disk reads:

Cache hit ratio trend

Track cache efficiency over time:

Queries spilling to temp files

Non-zero temp_blks_written means sorts or hashes are exceeding work_mem:

Track errors

Errors by SQLSTATE

Error rate over time

Errors for a specific query

Understand load patterns

QPS over time

Load by application

Rank applications by total query time to find the heaviest consumers:

Workload breakdown by command type

Monitor WAL and write activity

WAL generation rate

Full-page images (FPI) spike after each checkpoint then drop until the next one. This sawtooth pattern is visible in per-execution data but invisible in pg_stat_statements.

Dirty blocks over time

Buffer write pressure by block type. Spikes in shared blocks indicate write-heavy batches; non-zero local/temp indicate temp table or work_mem spill activity.

Analyze parallel query usage

Available on PostgreSQL 18+.

Queries where workers couldn’t be launched

If avg_missed is consistently high, consider increasing max_parallel_workers or max_worker_processes.

Analyze JIT compilation

Queries where JIT overhead exceeds benefit

If JIT compilation takes a large percentage of total execution time for frequently-run queries, consider raising jit_above_cost to prevent JIT for those queries.