Someone runs a query without a WHERE clause against a table with several hundred million rows. It will not finish in any useful time, and while it runs it holds a connection, blocks cleanup, and may hold locks that queue other work behind it.
The user who ran it has already closed their laptop.
A statement timeout ends that query automatically. It converts an open-ended resource drain into an error message.
What changed in 2026
- Timeouts became a default configuration item. Setting them moved from optional tuning to expected practice.
- Per-role and per-workload configuration spread. Different limits for application connections, analytics, and administrative sessions became standard.
- Idle-in-transaction timeouts got equal attention. Recognition that idle transactions cause more damage than slow queries.
- Pooler-level timeouts appeared. Connection poolers gained their own limits, adding a layer to configure.
Two different timeouts
They are frequently confused and they address different problems.
Statement timeout bounds how long a single statement may run. It stops the runaway query.
Idle-in-transaction timeout bounds how long a transaction may sit open doing nothing. It stops the application that opened a transaction, made a query, and then went off to call an external API for thirty seconds.
The second is the more common cause of trouble. A slow query is at least doing work; an idle open transaction holds locks and blocks cleanup while achieving nothing at all — see MVCC explained, where a single idle transaction can prevent reclamation across the entire database.
| Problem |
Bounded by |
| Query runs too long |
Statement timeout |
| Transaction open and idle |
Idle-in-transaction timeout |
| Connection idle outside a transaction |
Idle session timeout |
| Waiting to acquire a lock |
Lock timeout |
Setting only a statement timeout leaves the most damaging case unbounded.
Per workload, not globally
A single global value cannot serve everything.
An interactive user request should fail in seconds — anything longer is a bad experience and probably a bug. A scheduled report may legitimately run for minutes. A migration may need much longer.
Setting one value forces a compromise that is wrong for both: tight enough for reports to fail, loose enough for user requests to hang.
The workable approach is defaults per role or per connection, overridden per session where a specific operation needs longer. A reporting role with a generous limit, an application role with a tight one, and explicit per-session overrides for maintenance work.
Choose values from measurement rather than intuition. Look at your actual query duration distribution and set the limit above the legitimate tail, not at the median.
What a timeout does not fix
A timeout is a safety net, not a solution. A query hitting a timeout is a query that needed attention — a missing index, a bad plan, or a genuinely unreasonable request.
Timeouts firing regularly is a signal, and treating them as normal is how a performance problem becomes permanent. Log them, and treat a rising rate as a symptom worth investigating — the slow query log is the natural companion here, per slow query logs.
There is also a subtlety with cancellation: a statement cancelled partway may leave work to be undone, and rolling back a large partially-complete operation takes time of its own. A timeout that fires during a huge update does not free resources instantly.
Common mistakes
- No timeouts at all. One bad query degrades everything.
- Only a statement timeout. Leaves idle transactions unbounded.
- One global value. Wrong for both interactive and analytical work.
- Values set from intuition. Measure the distribution first.
- Treating timeouts as normal. They indicate a problem.
- Not configuring the pooler's timeouts. Another layer that can hold connections.
- Very long timeouts on user-facing roles. Users have already left.
FAQ
What values should I use?
Derived from your own query duration distribution — set above the legitimate tail for each workload. Interactive work typically wants seconds; analytical work tolerates far more.
Can a timeout roll back partial work?
Yes — the statement is cancelled and its effects undone. Undoing a large partially-complete operation takes time, so cancellation is not instant.
Does this help with lock contention?
Indirectly, by bounding how long a lock holder can run. A dedicated lock timeout is the direct control — see lock timeouts.
What about the application's own timeout?
Both are worth having. The application's timeout stops waiting; the database's timeout stops the query. Without the database side, the query keeps running after the client gives up.
Where to go next
For bounding lock waits specifically, read lock timeouts. For finding the queries that hit them, slow query logs, and for cancelling in-flight work, query cancellation.