Skip to content

python.db.missing_timeout

Stability High

Detects database connections and queries that don’t have proper timeout configuration, which can lead to hanging connections and cascading failures.

Database connections without timeouts can:

  • Hang indefinitely — Network issues can cause connections to wait forever
  • Exhaust connection pools — Stuck connections are never returned to the pool
  • Cause cascading failures — Application workers get blocked waiting for DB
  • Prevent graceful shutdown — Long-running queries ignore shutdown signals
# ❌ Before (no timeout)
from sqlalchemy import create_engine
engine = create_engine("postgresql://localhost/db")
# ✅ After (with timeout)
from sqlalchemy import create_engine
engine = create_engine(
"postgresql://localhost/db",
connect_args={"connect_timeout": 10},
pool_pre_ping=True, # Also recommended
)
  • SQLAlchemy create_engine() without connect_args timeout
  • SQLAlchemy create_async_engine() without timeout
  • psycopg2/psycopg connect() without connect_timeout
  • asyncpg connect() without timeout parameter

Unfault generates patches that add appropriate timeout parameters:

# SQLAlchemy (sync)
engine = create_engine(
DATABASE_URL,
connect_args={"connect_timeout": 10},
)
# SQLAlchemy (async with asyncpg)
engine = create_async_engine(
DATABASE_URL,
connect_args={"timeout": 10}, # asyncpg uses 'timeout'
)
# psycopg2
conn = psycopg2.connect(dsn, connect_timeout=10)
# asyncpg
conn = await asyncpg.connect(dsn, timeout=10)
# Comprehensive SQLAlchemy configuration
engine = create_engine(
DATABASE_URL,
connect_args={
"connect_timeout": 10,
"options": "-c statement_timeout=30000", # 30s query timeout
},
pool_pre_ping=True, # Verify connections before use
pool_recycle=3600, # Recycle connections hourly
pool_timeout=30, # Max wait for connection from pool
)