Query Timeout Protection - Quick Reference
What is it?
Query timeout protection prevents resource exhaustion by automatically terminating queries that run longer than a configured time limit.
Quick Start
Enable Timeout
[storage]query_timeout_ms = 30000 # 30 seconds (recommended for production)export HELIOSDB_JWT_SECRET="$(openssl rand -hex 32)"heliosdb-lite start --data-dir ./mydb --config config.tomlThe timeout applies to every query on the server. The default is 300000 ms (5 minutes);
set a larger value for long-running batch work. 0 does not mean “no limit”: it times out
every scanning query at once.
Handle Timeout Errors
A query that exceeds the limit fails with an error your client receives like any other SQL error:
Query timeout: Query exceeded timeout limit of 5000ms (elapsed: 5124ms)import psycopg2
try: cur.execute("SELECT * FROM large_table")except psycopg2.Error as e: if "Query timeout" in str(e): # fall back to a cheaper query, or retry later cur.connection.rollback() else: raiseRecommended Timeout Values
| Environment | Timeout | Notes |
|---|---|---|
| Development | 60000 or more | 60s or longer for debugging |
| Production | 30000 | 30 seconds is a good default |
| Public API | 10000 | 10 seconds for user-facing queries |
| Background Jobs | 300000 | 5 minutes for batch processing (the default) |
| Admin Tools | 3600000 | One hour for maintenance operations |
Different environments use different configuration files, for example
config.dev.toml with a longer timeout and config.prod.toml with 30000.
Key Features
- On by default: 300000 ms (5 minutes) when the setting is left out
- Minimal overhead: <0.1% performance impact
- Thread-safe: Works with parallel execution
- Granular control: Configurable per database instance
Performance Impact
| Check Frequency | Overhead |
|---|---|
| Every 1000 rows | <0.1% |
Figures from internal tests (HeliosDB Lite, timeout check every 1000 rows); reproduce on your own hardware. The server checks the clock more often than in that test: every 100 rows for timeouts of 100 ms or more, every 50 rows below 100 ms and every 10 rows below 10 ms.
Limitations
- Granularity: Checked every 100 rows (every 50 or 10 rows for timeouts under 100 ms or 10 ms), not every row
- DDL Operations: Not protected (CREATE TABLE, etc.)
- Blocking I/O: Timeout suspended during I/O operations
Troubleshooting
Query Always Timing Out
Problem: Legitimate queries are timing out
Solution:
- Increase timeout:
query_timeout_ms = 60000(60s) - Optimize query (add indexes, reduce data scanned)
- Use LIMIT to reduce result set size
No Timeout Protection
Problem: Long queries still running
Solution:
- Check that
query_timeout_msis in the[storage]section - Check that the server was started with
--configpointing at that file - Restart the server after changing the file
Timeout Too Strict
Problem: Complex analytical queries failing
Solution:
- Increase timeout for specific workloads
- Use batch processing for large operations
- Run maintenance on a separate instance with a larger timeout
Security Best Practices
- Enable timeout in production
- Set conservative limits for public APIs
- Monitor timeout frequency
- Log timeout events
Further Reading
Summary
Query timeout protection provides:
- Protection against resource exhaustion
- Minimal performance overhead (<0.1%)
- Easy configuration (one line)
- A 5-minute default that you can raise or lower
Recommended Action: Lower the timeout to 30 seconds for production deployments.