Skip to content

Settings

Database.from_env(), DatabaseCluster.from_env() and the lazily built default database all read their configuration from environment variables (or a .env file) through pydantic-settings, with the DATABASE_ prefix.

export DATABASE_URL="postgresql+asyncpg://user:pass@localhost:5432/app"
export DATABASE_POOL_SIZE=20
export DATABASE_POOL_PRE_PING=true
from sqlargon import Database

db = Database.from_env()
db = Database.from_env(echo=True)   # explicit keywords win over the environment

DatabaseSettings

Variable Default Meaning
DATABASE_URL postgresql+asyncpg://localhost:5432 async SQLAlchemy connection URL
DATABASE_ECHO false log every statement
DATABASE_ISOLATION_LEVEL engine isolation level
DATABASE_JSON_SERIALIZER sqlargon.utils:json_dumps callable used to serialize JSON
DATABASE_JSON_DESERIALIZER sqlargon.utils:json_loads callable used to deserialize JSON
DATABASE_CONNECT_ARGS JSON object passed to the DBAPI
DATABASE_ENABLE_TRACKER false attach the connection tracker
DATABASE_POOLCLASS import path of a Pool subclass
DATABASE_POOL_SIZE connections kept in the pool
DATABASE_MAX_OVERFLOW connections allowed beyond pool_size
DATABASE_ECHO_POOL log pool checkouts and returns
DATABASE_POOL_RECYCLE recycle connections after N seconds
DATABASE_POOL_PRE_PING test connections before handing them out
DATABASE_POOL_TIMEOUT seconds to wait for a free connection
DATABASE_POOL_USE_LIFO reuse the most recently returned connection

Unset options are omitted rather than passed as None, so SQLAlchemy's own defaults apply. Extra DATABASE_* variables are allowed and forwarded to create_async_engine, which makes engine options the library does not name explicitly reachable without a code change.

DATABASE_JSON_SERIALIZER, DATABASE_JSON_DESERIALIZER and DATABASE_POOLCLASS are import strings in module:object form:

export DATABASE_POOLCLASS="sqlalchemy.pool:NullPool"
export DATABASE_JSON_SERIALIZER="myapp.json:dumps"

DatabaseClusterSettings

DatabaseCluster.from_env() reads everything above plus:

Variable Default Meaning
DATABASE_READ_REPLICAS JSON array of replica URLs
DATABASE_AUTO_ROUTE true send SELECTs to replicas automatically
DATABASE_REPLICA_STRATEGY random random or round_robin
export DATABASE_URL="postgresql+asyncpg://primary/app"
export DATABASE_READ_REPLICAS='["postgresql+asyncpg://replica-1/app", "postgresql+asyncpg://replica-2/app"]'
export DATABASE_REPLICA_STRATEGY=round_robin

Replicas inherit the primary's engine options and become ReadOnlyDatabase members named replica_0, replica_1, ... alongside primary. DATABASE_READ_REPLICAS also decides what the lazily built default database is: with replicas configured it is a DatabaseCluster, otherwise a plain Database. See Database Routing.

Using the settings objects directly

from sqlargon import Database
from sqlargon.settings import DatabaseSettings

settings = DatabaseSettings(url="sqlite+aiosqlite:///app.db", echo=True)
db = Database(**settings.to_kwargs())

to_kwargs() returns the keyword arguments for the matching constructor, with unset options excluded. Both settings classes are ordinary pydantic-settings models, so they can be nested in an application-wide settings object.

Connection tracker

enable_tracker=True (or DATABASE_ENABLE_TRACKER=true) attaches sqlargon.tracker.TRACKER to the engine's pool. It is a test and debugging utility that records which connections are currently checked out, with the stack trace that opened them:

from sqlargon.tracker import TRACKER

assert not TRACKER.open_connections, TRACKER.open_connections
print(TRACKER.connects, TRACKER.closes)
TRACKER.clear()

OpenTelemetry

When opentelemetry-instrumentation-sqlalchemy is installed (the opentelemetry extra), every Database instruments its engine automatically on construction — no configuration required beyond setting up your tracer provider.