Skip to content

Query Timeout Protection - Quick Reference

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

use heliosdb_nano::{EmbeddedDatabase, Config};
let mut config = Config::default();
config.storage.query_timeout_ms = Some(30000); // 30 seconds
let db = EmbeddedDatabase::new_with_config(config)?;

Handle Timeout Errors

use heliosdb_nano::Error;
match db.query("SELECT * FROM large_table") {
Err(Error::QueryTimeout(msg)) => {
println!("Query timed out: {}", msg);
// Handle timeout
}
Ok(results) => {
println!("Success: {} rows", results.len());
}
Err(e) => {
println!("Error: {}", e);
}
}

Configuration

Via Config File (TOML)

[storage]
query_timeout_ms = 30000 # 30 seconds (recommended for production)

Via Code

// Set timeout
config.storage.query_timeout_ms = Some(5000); // 5 seconds
// Disable timeout
config.storage.query_timeout_ms = None; // Unlimited (default)
EnvironmentTimeoutNotes
DevelopmentNone or 60000Unlimited or 60s for debugging
Production3000030 seconds is a good default
Public API1000010 seconds for user-facing queries
Background Jobs3000005 minutes for batch processing
Admin ToolsNoneUnlimited for maintenance operations

Error Message Format

Query timeout: Query exceeded timeout limit of 5000ms (elapsed: 5124ms)

Key Features

  • Zero-config compatibility: Disabled by default
  • Minimal overhead: <0.1% performance impact
  • Thread-safe: Works with parallel execution
  • Granular control: Configurable per database instance

Performance Impact

Check FrequencyOverheadCurrent Setting
Every 1000 rows<0.1%Default

Limitations

  1. Granularity: Checked every 1000 rows, not every row
  2. DDL Operations: Not protected (CREATE TABLE, etc.)
  3. Blocking I/O: Timeout suspended during I/O operations

Common Use Cases

Prevent Runaway Queries

// Prevent expensive queries from running forever
config.storage.query_timeout_ms = Some(30000);

Different Timeouts for Different Environments

let timeout = if cfg!(debug_assertions) {
None // Unlimited in development
} else {
Some(30000) // 30 seconds in production
};
config.storage.query_timeout_ms = timeout;

Graceful Degradation

match db.query(complex_query) {
Err(Error::QueryTimeout(_)) => {
// Fall back to simpler query
db.query(simple_query)?
}
result => result,
}

Troubleshooting

Query Always Timing Out

Problem: Legitimate queries are timing out

Solution:

  1. Increase timeout: query_timeout_ms = Some(60000) (60s)
  2. Optimize query (add indexes, reduce data scanned)
  3. Use LIMIT to reduce result set size

No Timeout Protection

Problem: Long queries still running

Solution:

  1. Verify configuration: config.storage.query_timeout_ms.is_some()
  2. Check error handling catches Error::QueryTimeout
  3. Ensure database created with updated config

Timeout Too Strict

Problem: Complex analytical queries failing

Solution:

  1. Increase timeout for specific workloads
  2. Use batch processing for large operations
  3. Consider disabling timeout for admin operations

Migration from v1.x

No breaking changes!

Timeout is disabled by default. To enable:

// Before (v1.x)
let db = EmbeddedDatabase::new()?;
// After (v2.x with timeout)
let mut config = Config::default();
config.storage.query_timeout_ms = Some(30000);
let db = EmbeddedDatabase::new_with_config(config)?;

Security Best Practices

Enable timeout in productionSet conservative limits for public APIsMonitor timeout frequencyLog timeout events

Further Reading

Summary

Query timeout protection provides:

  • Protection against resource exhaustion
  • Minimal performance overhead (<0.1%)
  • Easy configuration (one line)
  • Backward compatible (disabled by default)
  • Production-ready security enhancement

Recommended Action: Enable with 30 second timeout for all production deployments.