"pg_stat_statements: Find Your App's Slowest Query in 15 Minutes"
"Find slow queries with pg_stat_statements — enable the extension, read total vs mean exec time, spot N+1 patterns, and reset stats with copy-paste SQL."
Every slow app has the same bottleneck shape: one or two queries eating 80% of database time, hiding behind an endpoint that "feels fine" until traffic grows. This guide shows you how to find slow queries with pg_stat_statements , PostgreSQL's built-in query-statistics extension — enable it in two steps, run one diagnosis query, and learn to read total vs mean execution time so you fix what actually hurts instead of what merely looks slow. Last updated: October 4, 2026 What you'll learn How to enable pg_stat_statements (and why shared_preload_libraries is the usual blocker) The one query that ranks your app's queries by real cost total_exec_time vs mean_exec_time : which one to sort by, and when How to detect N+1 query patterns from the stats view How to reset pg_stat_statements before a measurement run The Supabase pre-enabled shortcut and its one caveat How to Enable pg_stat_statements pg_stat_statements is a contrib extension, and on a self-hosted Postgres it needs one server-level step before CREATE EXTENSION will work: the library must be preloaded at server start. Without it you get the famous error pg_stat_statements must be loaded via shared_preload_libraries . # postgresql.conf shared_preload_libraries = 'pg_stat_statements' pg_stat_statements.track = 'top' # track top-level statements (the default; 'all' includes nested) Restart Postgres, then enable it in your database: CREATE EXTENSION IF NOT EXISTS pg_stat_statements; SELECT * FROM pg_stat_statements LIMIT 1; -- should return stats, not an error On Docker, set the preload through the command flag instead of editing the conf file: docker run -d --name pg \ -e POSTGRES_PASSWORD=secret \ postgres:17 \ -c shared_preload_libraries=pg_stat_statements On Supabase,…