José Agretti
02/17/2026, 2:41 PMMarvin
02/17/2026, 2:41 PMMarvin
02/17/2026, 2:45 PM# Environment variables
PREFECT_SERVER_DATABASE_SQLALCHEMY_POOL_SIZE=5
PREFECT_SERVER_DATABASE_SQLALCHEMY_MAX_OVERFLOW=10
PREFECT_SERVER_DATABASE_SQLALCHEMY_POOL_RECYCLE=3600
PREFECT_SERVER_DATABASE_SQLALCHEMY_POOL_TIMEOUT=30.0
Or in prefect.toml:
[server.database.sqlalchemy]
pool_size = 5
max_overflow = 10
pool_recycle = 3600
pool_timeout = 30.0
Hardcoded (not configurable)
- pool_pre_ping = True
- pool_use_lifo = True
Source links (Prefect 3.6.5)
- Settings model (env var names and defaults): https://github.com/PrefectHQ/prefect/blob/3.6.5/src/prefect/settings/models/server/database.py
- Engine/pool configuration (pre_ping, LIFO, etc.): https://github.com/PrefectHQ/prefect/blob/3.6.5/src/prefect/server/database/configurations.py
Practical tips
- Start with small pools (e.g., pool_size=5, max_overflow=10) and observe. Increase if you see pool timeouts; decrease if Postgres is connection-starved.
- Remember to multiply by any process-level concurrency you use (e.g., multiple uvicorn workers).
- If you front Postgres with PgBouncer, ensure settings are compatible with asyncpg and prepared statement caching.
If you share how many API instances/workers you plan to run (and your Postgres max_connections), I can help you pick pool settings and a safe headroom.José Agretti
02/17/2026, 2:48 PMprefect server start --host 0.0.0.0 --port 4200 --no-services
And Postgres has 400 max connections @MarvinMarvin
02/17/2026, 2:48 PMMarvin
02/17/2026, 2:49 PM# Cap total connections while keeping solid baseline concurrency
PREFECT_SERVER_DATABASE_SQLALCHEMY_POOL_SIZE=5
PREFECT_SERVER_DATABASE_SQLALCHEMY_MAX_OVERFLOW=5
# Optional tuning
PREFECT_SERVER_DATABASE_SQLALCHEMY_POOL_RECYCLE=3600
PREFECT_SERVER_DATABASE_SQLALCHEMY_POOL_TIMEOUT=30.0
Notes
- Pools are per-process. If you ever run multiple workers per API process, multiply accordingly.
- pool_pre_ping and pool_use_lifo are always enabled (good for health and reducing churn).
- SQLAlchemy opens connections on demand; the “max” math above is for capacity planning.
Helpful links (exact settings in source)
- Settings (env var names and defaults): https://github.com/PrefectHQ/prefect/blob/3.6.5/src/prefect/settings/models/server/database.py
- Engine/pool configuration (pre_ping, LIFO, etc.): https://github.com/PrefectHQ/prefect/blob/3.6.5/src/prefect/server/database/configurations.py
If you can share whether each API server runs a single process (no extra workers) and your typical peak request rate, I can help dial in the exact pool_size/overflow combo and a safe headroom target.José Agretti
02/17/2026, 2:52 PMMarvin
02/17/2026, 2:52 PMMarvin
02/17/2026, 2:55 PMPREFECT_SERVER_DATABASE_SQLALCHEMY_POOL_SIZE=5
PREFECT_SERVER_DATABASE_SQLALCHEMY_MAX_OVERFLOW=5
PREFECT_SERVER_DATABASE_SQLALCHEMY_POOL_RECYCLE=3600
PREFECT_SERVER_DATABASE_SQLALCHEMY_POOL_TIMEOUT=30.0
Optional (prefect.toml)
[server.database.sqlalchemy]
pool_size = 5
max_overflow = 5
pool_recycle = 3600
pool_timeout = 30.0
Quick Postgres check
SELECT
count(*) AS total,
count(*) FILTER (WHERE state='active') AS active,
count(*) FILTER (WHERE state='idle') AS idle
FROM pg_stat_activity;
For reference on the exact settings and defaults (verified in 3.6.5 source):
- Settings model (env var names and defaults): https://github.com/PrefectHQ/prefect/blob/3.6.5/src/prefect/settings/models/server/database.py
- Engine/pool behavior (pre_ping, LIFO): https://github.com/PrefectHQ/prefect/blob/3.6.5/src/prefect/server/database/configurations.py
Follow-up question: Do you have a separate, single API instance running with services enabled (scheduler, late runs), or are all 25 started with --no-services? That affects how much DB headroom we should reserve.