OpenHands / OpenHands/enterprise
DB connection pool defaults too high and not env-tunable, exhausting Postgres in distributed deploys
@dylan-openhands is already working on this.
Since Jul 14, 2026.
- Dominant language
- Python
- Stars
- 4
- Forks
- 2
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 101
Description
Problem
DbSessionInjector (openhands/app_server/services/db_session_injector.py) defaults to pool_size=25 — 5× SQLAlchemy's default of 5 — and pool_size/max_overflow are not wired to any env var, so they can't be tuned without a code change.
Every process holds its own pool, so total connections scale as pool_size × workers × replicas. At pool_size=25 you can only run floor(max_connections / 25) processes before the idle floor alone saturates Postgres (4 processes on a default max_connections=100; 60 at 1,500).
Impact
In a production setting (15 replicas × 3 workers = 45 processes) this held ~1,125 idle connections at all times with a ~1,575 burst ceiling against Cloud SQL max_connections ≈ 1,500 — before other clients — surfacing as sqlalchemy.exc.TimeoutError: QueuePool limit of size 25 overflow 10 reached. Observed 30-day p95: active ≈ 1.5, idle ≈ 752, i.e. ~100× over-provisioned.
Fix
- Lower the
pool_sizedefault25 → 5(align with SQLAlchemy;max_overflowstays10). - Read
DB_POOL_SIZE/DB_MAX_OVERFLOWfrom env (same names the Alembic runner already uses) so deployments can tune pooling without code changes.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.