dataiotech Labs
dbaguidedbaguideDBAdataxtoolsdataopsphere
Home/Error Library/postgresql-canceling-statement-statement-timeout
PostgreSQL
PostgreSQL 14–18Performance & Locks
8 min read
ERROR: canceling statement due to statement timeout (SQLSTATE 57014)

PostgreSQL "canceling statement due to statement timeout" — Slow Query or Lock Contention?

Deconstructing SQLSTATE 57014: statement timeout vs lock timeout vs user request vs recovery conflict. Tracing settings origin in pg_settings and tiered role thresholds.

Reviewed by:Principal Database Reliability Architect
Tested Versions: PostgreSQL 18.6 & 17.11 (Alpine Linux / Docker 29.7) | Tarihsel: PostgreSQL 14, 15, 16

Operational Verification & Reliability Metadata

Last Technical Review: 30 Ekim 2026
Tested VersionsPostgreSQL 18.6 & 17.11 (Alpine / Docker 29.7) | Tarihsel: PostgreSQL 14.10, 15.6, 16.4
Required PrivilegesSUPERUSER or pg_read_all_stats (to inspect pg_stat_statements and pg_blocking_pids)
Risk Assessment
MediumSetting global statement_timeout to 0 disables safety nets, resulting in connection pool exhaustion during load spikes
Expected OutputDisambiguation of 4 distinct SQLSTATE 57014 events: query timeout, lock timeout, client cancel, and standby conflict
Rollback Procedure:Enforce tiered timeouts per role (web vs batch) and set lock_timeout shorter than statement_timeout
PostgreSQL Docs: Statement Timeout Configuration
First 60 Seconds Emergency Protocol:

The error string is a symptom, not the root cause. Do not restart the server blindly. Run the diagnostic queries below to pinpoint the actual failure mode.

▸Symptom

plaintext
ERROR: canceling statement due to statement timeout

Under PostgreSQL SQLSTATE code 57014 (query_canceled), four entirely different operational events can occur:

plaintext
ERROR: canceling statement due to statement timeout ERROR: canceling statement due to lock timeout ERROR: canceling statement due to user request ERROR: canceling statement due to conflict with recovery
IMPORTANT
Diagnose by Error Text, Not SQLSTATE! Seeing 57014 and assuming *"the query is slow, let's add an index"* leads engineers down the wrong path in three out of four cases: - `statement timeout`: The query actively consumed CPU/IO and exceeded the allotted runtime threshold. - `lock timeout`: The query execution could be sub-millisecond, but it was blocked waiting for an exclusive lock held by another transaction! Adding indexes will not help (H-19, H-27). - `user request`: The cancellation was issued by the client application (JDBC setQueryTimeout, .NET CommandTimeout, Go context deadline). The client explicitly transmitted a cancel request; server-side database configuration is not at fault. - `conflict with recovery`: The query was executing on a Standby Read Replica and was cancelled due to competing WAL replay operations from the primary (H-11).

▸Tracing Configuration Sources via `pg_settings`

In PostgreSQL, statement_timeout can originate from five distinct configuration levels:

sql
SELECT name, setting, unit, source, sourcefile, sourceline FROM pg_settings WHERE name IN ('statement_timeout', 'lock_timeout', 'idle_in_transaction_session_timeout');

The source column determines the winning override:

  • •configuration file: Global configuration from postgresql.conf.
  • •database: Applied via ALTER DATABASE ... SET.
  • •user: Applied via ALTER ROLE ... SET.
  • •client: Injected dynamically by the application driver or connection pooler.
  • •default: Unset; defaults to 0 (unlimited).

▸Step-by-Step Diagnostic Workflow

1. Measure Long-Running Queries via pg_stat_statements

sql
CREATE EXTENSION IF NOT EXISTS pg_stat_statements; SELECT queryid, calls, round(mean_exec_time::numeric, 1) AS avg_ms, round(total_exec_time::numeric) AS total_ms, left(query, 100) AS query_text FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 15;
  • •total_exec_time identifies the top cumulative resource hogs.
  • •mean_exec_time highlights individual queries that breach timeout thresholds.

2. Check for Lock Contention

sql
SELECT pid, now() - query_start AS duration, wait_event_type, wait_event, cardinality(pg_blocking_pids(pid)) AS blocker_count, pg_blocking_pids(pid) AS blocker_pids, left(query, 80) AS query_text FROM pg_stat_activity WHERE state = 'active' AND pid <> pg_backend_pid() ORDER BY duration DESC;

If wait_event_type = 'Lock', the query is stalled waiting for a lock, not consuming CPU.

3. Inspect Query Execution Plans with Buffers

sql
EXPLAIN (ANALYZE, BUFFERS) SELECT ...;

The BUFFERS clause is critical: it distinguishes queries reading from shared RAM cache (shared hit) from those thrashing disk subsystems (read).


▸Production Best Practices: Tiered Timeout Policies

1. Never Disable Timeouts Globally

Setting global statement_timeout = 0 disables critical safety mechanisms. A runaway query will simply consume connection pool slots and bring down the entire cluster under peak load.

2. Define Tiered Timeouts per Role

Web APIs and reporting batches must operate under separate timeout rules:

sql
-- Interactive web tier (5 seconds) ALTER ROLE app_web SET statement_timeout = '5s'; -- Batch reporting service (15 minutes) ALTER ROLE app_reporting SET statement_timeout = '15min';

3. Set lock_timeout Lower than statement_timeout

sql
ALTER SYSTEM SET lock_timeout = '3s'; ALTER SYSTEM SET statement_timeout = '10s'; SELECT pg_reload_conf();

When lock contention occurs, the query fails early with lock timeout rather than holding up connection pool threads for the full 10 seconds.


▸Related Error Guides & Hub Links

Other Database Error Triage Playbooks

Other battle-tested diagnostic guides for high-severity database errors.

All Errors (50)