At a glance
| Supported databases | PostgreSQL (shipped as a contrib module) |
| Query analysis | Cumulative statistics per normalised statement |
| Execution plans | Not captured (pair with auto_explain) |
| Wait statistics | Not captured (wait events are in pg_stat_activity) |
| Index recommendations | None |
| Slow-query detection | Order by total or mean execution time; no alerting |
| Tuning automation | None; it is a statistics source |
| Configuration | pg_stat_statements.max 5000, track top, track_utility on, track_planning off, save on (defaults) |
| Licensing | PostgreSQL Licence, free |
Enable pg_stat_statements on every PostgreSQL server you care about. It is free, ships with PostgreSQL, and tells you which statements use the most time, I/O and WAL. It stores cumulative counters only, with no history, plans or alerting, so for trends you need something that samples it over time.
Overview
pg_stat_statements is one of the additional modules shipped with PostgreSQL. Once loaded, it groups statements that differ only in literal values (constants become $1, $2 and lists collapse) and keeps one row per database, user, query ID and top-level flag, with counts, timings, rows, buffer, I/O timing, WAL, JIT and parallel worker statistics. Query texts go to an external file rather than shared memory.
Setup takes three steps: add it to shared_preload_libraries (a restart is needed because it allocates shared memory), make sure compute_query_id is auto or on, and run CREATE EXTENSION pg_stat_statements in each database where you want the views. Statistics are collected server-wide. Superusers and members of pg_read_all_stats can see every user's query text; other users see only their own.
Key features
- Per-statement calls, total, mean, min, max and standard deviation of execution time, and rows
- Optional planning time statistics (pg_stat_statements.track_planning, off by default)
- Shared, local and temp block counters, with I/O timing columns when track_io_timing is on
- WAL records, full page images, bytes and wal_buffers_full, plus JIT and parallel worker columns
- pg_stat_statements_info view showing deallocations and the last reset time
- pg_stat_statements_reset() by user, database or query ID, or min/max values only
- Constant normalisation so similar statements are aggregated, with a queryid stable across physical replicas
Integrations and ecosystem
Pros and cons
Pros
- Free and part of every standard PostgreSQL distribution
- Widely available on managed PostgreSQL services
- Shows where time, I/O and WAL go across all statements
- Feeds tools such as pganalyze, PMM, pgwatch and Datadog
Cons
- Needs a server restart to load through shared_preload_libraries
- Cumulative counters only: no history, no plans and no alerts on its own
- Least-used entries are discarded once pg_stat_statements.max is reached
- queryid is not guaranteed stable across major versions
Pricing
pg_stat_statements is distributed with PostgreSQL as an additional supplied module under the PostgreSQL Licence, so it costs nothing. On a managed PostgreSQL service it comes with the service you already pay for.
Pricing checked on the vendor's official page on 7 November 2026. Prices change; confirm before buying.
Who it is best for
Every PostgreSQL deployment, as the first source to check when you need to know which statements consume the most time or I/O.
Typical use cases
- Finding the statements with the highest total execution time
- Spotting statements with high temp block or WAL usage
- Measuring the effect of an index or query change by resetting and comparing statistics
- Feeding a monitoring tool that samples the view over time
Who should look elsewhere
- Teams wanting dashboards, history and alerting out of the box: see PostgreSQL monitoring tools.
Verdict
pg_stat_statements is the essential, free starting point for PostgreSQL query performance work. Turn it on early, size pg_stat_statements.max for your workload, and add a monitoring tool when you need history, plans and alerts.
Frequently asked questions
How do I enable pg_stat_statements?
Add pg_stat_statements to shared_preload_libraries in postgresql.conf, restart the server, make sure compute_query_id is auto or on, then run CREATE EXTENSION pg_stat_statements in each database where you want to query the view.
Does pg_stat_statements store query plans?
No. It stores statistics per normalised statement. For plans of slow statements use the auto_explain module or a monitoring tool.
How many statements does it track?
Up to pg_stat_statements.max, 5000 by default, set at server start. When more distinct statements appear, the least-executed entries are discarded and pg_stat_statements_info.dealloc increases.
Is pg_stat_statements free?
Yes. It ships with PostgreSQL under the PostgreSQL Licence.
Sources
- pg_stat_statements (PostgreSQL documentation)
- Run-time statistics settings: compute_query_id and track_io_timing (PostgreSQL documentation)
- auto_explain (PostgreSQL documentation)
- PostgreSQL Licence
Checked November 2026.
Listed in: Performance & Query Optimization.
How we research reviews and what star ratings mean: our editorial method.