`run_sql` leaks session state across requests in Postgres

Author: gabegorelickCreated Jun 26, 2026Updated Jun 26, 2026
Labelsk/bug

Version Information

Server Version: 2.48.5 CLI Version (for CLI related issue): n/a

Environment

OSS

What is the current behaviour?

Any session-scoped state established within a run_sql request persists on the underlying Postgres connection after the request finishes, and is inherited by subsequent, unrelated requests — including GraphQL query execution — that reuse that connection from the pool. The engine performs no session reset (DISCARD / RESET ALL) when returning a connection to the pool.

One way this issue can manifest is via migrations. For example, let's say your migration contains a SET statement_timeout to limit how long your DDL can run. That statement_timeout will be applied to subsequent queries on that session until connection_lifetime or a similar setting kills the session.

What is the expected behaviour?

A session change made by one request should not affect subsequent, unrelated requests.

How to reproduce the issue?

  1. Configure a single Postgres source with pool_settings.max_connections: 1. This forces connection reuse so the leak is deterministic. With a larger pool the leak still occurs, just nondeterministically on whichever connection ran the statement.
  2. Call run_sql and do something that modifies the session. E.g. SET statement_timeout = '1ms'.
  3. Call run_sql again and observe that statement_timeout is now 1ms.

Screenshots or Screencast

Please provide any traces or logs that could help here.

Any possible solutions/workarounds you're aware of?

Hasura could call DISCARD ALL before returning connections to its pool. In lieu of that, it's up to callers to do that themselves in the SQL they run. But that is easier said then done:

sql
-- Assume this is a migration that is not wrapped in a transaction.
SET statement_timeout = 1000;

-- Assume this times out
CREATE INDEX CONCURRENTLY ...;

-- This won't run
RESET statement_timeout

Keywords