Back to Blog

Why Your AI Database Query Times Out (and How to Fix It)

Your AI's query worked on a small table and times out on a big one. What's actually timing out — the database, the gateway, or the AI client — and how to fix each layer without giving the AI unlimited time on production.

The same question worked fine last week. Today, against a bigger table, the AI just... stops, and you get some version of "the query timed out" or "request failed" with no obvious reason why.

The confusing part is that "timeout" isn't one setting — it's usually three separate limits stacked on top of each other, and whichever one is smallest wins, silently.

The three layers, and which one you're actually hitting

1. The database's own statement timeout. Postgres has statement_timeout; SQL Server has a request timeout on the connection. Both exist independently of anything your AI tooling does, and both commonly default to something conservative — 30 seconds is a typical out-of-the-box value. If your query needs 45 seconds to run, the database kills it at 30 no matter what any other layer allows.

2. The MCP gateway's own limit. A gateway sitting between the AI and your database (Synra, or a self-hosted MCP server) has to set its own query timeout too — otherwise one runaway query could hang a connection indefinitely. If the gateway's limit is lower than the database's, the gateway cuts it off first.

3. The AI client or hosting platform's execution limit. If the gateway itself runs on a serverless platform, that platform has its own maximum function duration, separate from both of the above. A gateway that raises its internal query timeout to 120 seconds still fails if the serverless function hosting it gets killed at 60.

The failure you see is usually generic — "query failed," "request timed out," sometimes nothing more specific — because whichever layer cut it off first doesn't necessarily know or say which of the three it was.

Why this shows up more with certain databases

Long-running aggregate queries against systems like Dataverse-backed SQL Server instances, or big analytics tables in Postgres, hit this constantly, simply because the underlying query has more rows to scan and joins are heavier. A quick lookup query almost never hits any of these limits; a multi-table join with a GROUP BY over months of data is exactly the shape that does.

This is also where reserved word syntax errors and timeouts get confused with each other in a bug report — "the query failed" covers both, but they need completely different fixes. A syntax error is instant; a timeout takes the full duration before it fails, which is your first clue which one you're looking at.

Fixing it layer by layer

Work from the database outward, since raising an outer limit does nothing if an inner one is still the bottleneck:

  1. Check the database's statement timeout first. In Postgres, this is a per-connection or per-role setting; ask your DBA or check the connection config. If it's the default 30 seconds and your legitimate queries need more, raise it — but only for the specific read-only role the AI connects as, not globally.
  2. Check the gateway's query timeout. If you're on a managed gateway, this is usually just a number in a config file or dashboard. Raise it to comfortably exceed the database timeout from step 1, not the other way around — the outer limit should always be looser than the inner one, or it becomes the new bottleneck.
  3. Check the hosting platform's function duration, if your gateway runs on serverless infrastructure. This needs to exceed the gateway's own timeout, for the same reason as step 2.
  4. Re-run the query. If it now completes, you're done for that specific query. If it still fails, the problem isn't timeout configuration anymore — it's genuinely how slow the query is.

When raising the timeout is the wrong fix

A query that reliably takes 90+ seconds against a table with a few million rows is usually telling you something about the query, not the timeout setting. Common causes:

  • A filter or join column with no index — the database is scanning far more rows than it needs to. See find missing indexes with AI for how to have the AI itself spot this.
  • execute_sql without a date range, pulling in years of history for a question that only needed last month.
  • A join that fans out — one side has duplicates, multiplying row counts before any aggregation happens.

Raising the timeout to 120 seconds so a 90-second query "works" is a reasonable stopgap once. Doing it as the permanent fix means every future query on that table pays the same tax, and a busy production table pays it in held-open connections and contention with other traffic — worth weighing against just fixing the index.

The version that actually holds up

Set the database timeout deliberately (not left on a default nobody chose on purpose), make sure the gateway and any hosting layer are configured looser than it — not tighter — and treat a slow query as a prompt to look at indexes before you treat it as a number to keep raising.


Read-only MCP gateway with query timeouts configured to actually match the database underneath: mcpserver.design.

Related reading: