🟪 Database

PostgreSQL pg_stat_statements Does Not Exist

The relation "pg_stat_statements" does not exist error occurs when an application or monitoring tool queries the pg_stat_statements view but the extension hasn’t been installed in the database. The extension ships with PostgreSQL but requires explicit configuration in shared_preload_libraries, a Postgres restart, and CREATE EXTENSION in each target database to be available.

TL;DR — The error doesn’t mean Postgres is broken — it means the query-stats extension isn’t installed. Three-step fix: add to shared_preload_libraries, restart Postgres, run CREATE EXTENSION in each target database. Managed providers (RDS, Aurora, Supabase) need the parameter-group change to be applied via reboot. The most common mistake is doing steps 1 or 3 but forgetting the others — Postgres will silently behave as if nothing changed.
pg_stat_statements
A Postgres contrib extension that tracks execution statistics for each unique SQL statement — call count, total time, mean time, rows returned. The standard data source for query-performance monitoring in any APM tool.
shared_preload_libraries
A Postgres configuration parameter listing shared libraries to preload at server start. Changes require a Postgres restart to take effect.
CREATE EXTENSION
The SQL command that loads an extension into a specific database. Per-database — running it in postgres doesn’t enable it in my_app.
contrib
The collection of optional Postgres extensions shipped alongside the core server. Most are installed by default in the contrib package but require explicit enablement to be active.
Parameter group (RDS/Aurora)
AWS-managed configuration bundle for RDS/Aurora instances. Changes to shared_preload_libraries happen here, not directly in postgresql.conf.
Not to be confused with pg_stat_statements (an extension you have to install) is distinct from pg_stat_activity (a built-in view, always available, shows currently-running queries) and other pg_stat_* views like pg_stat_database, pg_stat_user_tables — those are part of core Postgres and don’t require the extension. The error specifically tells you about pg_stat_statements, the historical aggregation view.

What does this error look like?

Two common surfaces:

From application code or monitoring tool querying the view directly:

ERROR: relation "pg_stat_statements" does not exist
LINE 1: SELECT query, calls, total_exec_time, mean_exec_time FROM pg_stat_statements
                                                                  ^
SQLSTATE: 42P01 (undefined_table)

From a Postgres collector / health check:

WARN  collector health check: failed to list query stats {
  "err": "ERROR: relation \"pg_stat_statements\" does not exist (SQLSTATE 42P01)"
}

Both come from the same root cause: the view doesn’t exist in the database being queried. Often surfaces the first time you connect a monitoring tool to a database that wasn’t provisioned with the extension.

Why does this happen?

pg_stat_statements is a Postgres contrib extension — meaning it’s shipped with Postgres but not auto-enabled. To use it, three things must all be true:

  1. The contrib package is installed on the Postgres server. This is usually true on managed providers and in most distros, but worth verifying with SELECT * FROM pg_available_extensions WHERE name = 'pg_stat_statements'.
  2. shared_preload_libraries includes pg_stat_statements — and Postgres has been restarted since this was added. This is the step most people miss; without it, the extension can’t be loaded.
  3. The extension is created in the target database via CREATE EXTENSION pg_stat_statements. Extensions are per-database. Creating it in postgres does not enable it in your application’s database.

The most common failure mode: someone runs CREATE EXTENSION but skipped the shared_preload_libraries step. The CREATE EXTENSION succeeds — but the extension isn’t actually loaded, so queries against pg_stat_statements still fail. Or vice versa: shared_preload_libraries is configured but CREATE EXTENSION was forgotten.

How severe is this?

ContextSeverityReasoning
APM / monitoring tool depends on itMajorQuery-performance visibility goes dark; slow-query investigation becomes guesswork
One-off DBA script needs itMinorEasy workaround — install for the investigation, no production impact
Application code queries it directlyMajorApplication errors out; user-visible if it’s in a hot path
Postgres core functionalityNonePostgres itself doesn’t need it — all standard queries work fine

How to install and fix

1. Confirm the extension is actually missing

SELECT * FROM pg_available_extensions WHERE name = 'pg_stat_statements';

Three possible outcomes:

  • No rows returned: the contrib package isn’t installed on the server. Install postgresql-contrib (or your distro’s equivalent) on self-hosted; contact your managed provider on RDS/Aurora/etc.
  • Row returned, installed_version is null: available but not loaded. Continue to step 2.
  • Row returned with installed_version: extension IS installed in this database. Your error is likely a permissions issue or you’re connected to the wrong database.

2. Add to shared_preload_libraries

On self-hosted Postgres, edit postgresql.conf:

shared_preload_libraries = 'pg_stat_statements'

If you already have other libraries listed, append:

shared_preload_libraries = 'pg_stat_statements,timescaledb,pg_cron'

3. Restart PostgreSQL

The shared_preload_libraries change requires a restart — reload isn’t enough.

sudo systemctl restart postgresql

Verify after restart:

SHOW shared_preload_libraries;

4. Run CREATE EXTENSION in each target database

\c my_app_db
CREATE EXTENSION pg_stat_statements;

Critical: do this in every database where you want query stats. Extensions are per-database, not per-cluster. A common mistake when adding new databases later.

5. Grant access to the monitoring user (Postgres 10+)

If your monitoring tool uses a non-superuser, it needs explicit access:

GRANT pg_read_all_stats TO monitoring_user;

Without this grant, queries against pg_stat_statements appear to succeed but return zero rows for non-superusers.

6. Verify with a test query

SELECT count(*) FROM pg_stat_statements;

Non-zero count confirms the extension is loaded and capturing. If the count is zero, run a few SELECT queries against your tables and re-check — pg_stat_statements only records queries executed after it loaded.

Managed Postgres specifics

Each managed Postgres provider requires slightly different setup for shared_preload_libraries:

ProviderHow to add to shared_preload_librariesRestart needed?
Amazon RDSEdit DB parameter group → add pg_stat_statements to shared_preload_librariesYes — reboot the DB instance
Amazon AuroraDB cluster parameter group → same fieldYes — reboot
Google Cloud SQLEdit instance flags → add cloudsql.enable_pg_stat_statements=onYes — restart instance
Azure Database for PostgreSQLServer parameters → set pg_stat_statements.track=all + shared_preload_libraries already includes it by default on Flexible ServerYes
SupabaseAlready enabled by default. CREATE EXTENSION pg_stat_statements in your project’s DB if missingUsually no — already loaded
Heroku PostgresAvailable on Standard tier and above. CREATE EXTENSION in your databaseNo — managed
Neon, Crunchy, RenderUsually enabled or trivially toggleable in dashboardVaries

The pattern across managed providers: shared_preload_libraries is configured at the platform layer (parameter group, instance flag), not directly. Always check the provider’s docs for the exact UI path — the underlying Postgres mechanism is the same, the management surface differs.

How Dstl8 detects this

Dstl8’s data-source collector surfaces missing-extension errors immediately when connecting to a new Postgres source. Here’s an actual detection from a Dstl8 customer’s onboarding flow (anonymized):

Real detection · anonymized
Powered by CONTROLTHEORY
Incident Active ACME-PROD

SQL execution error: relation pg_stat_statements does not exist in customer-portal

Postgres query-stats extension not installed in target database. Connector returning SQLSTATE 42P01 on every health-check cycle. Impact: query-performance monitoring unavailable for the customer-portal source. Recommend: enable pg_stat_statements via shared_preload_libraries + CREATE EXTENSION in the target database.

Started
14:37
May 14
Duration
41m
Severity
Major
Events
1

Three details to notice:

  1. The incident title is exact-match for the SQL error. Engineers searching the literal error string land directly here — both in your logs and in Google.
  2. The recommended remediation is specific. Not “investigate” — actual fix steps in the right order (shared_preload_libraries first, then CREATE EXTENSION). Saves the on-call from rediscovering the gotcha.
  3. The downstream impact is named. “Query-performance monitoring unavailable for this source” — explains why this matters, not just that an error happened.

Related patterns

References

Catch missing-extension errors the moment they hit your Postgres source.

Dstl8 surfaces specific SQL errors with named remediation steps — including the gotchas around shared_preload_libraries and managed Postgres providers.

Start Free 14-Day Trial →