Configuration and Routing
Ryx supports explicit setup, import-time auto-initialization, multiple database aliases, per-model database metadata, and a global database router.
Explicit Setupโ
import ryx
await ryx.setup("sqlite:///app.db")
For multiple databases, pass a mapping:
await ryx.setup({
"default": "postgres://user:pass@localhost/app",
"replica": "postgres://user:pass@localhost/app_replica",
"analytics": "sqlite:///analytics.db",
})
Pool options:
await ryx.setup(
{"default": "sqlite:///app.db"},
max_connections=10,
min_connections=1,
connect_timeout=30,
idle_timeout=600,
max_lifetime=1800,
)
Auto Initializationโ
On import, Ryx attempts auto-initialization unless disabled:
export RYX_AUTO_INITIALIZE=0
Disabling values are 0, false, n, and no.
Auto-init reads database URLs from:
export RYX_DATABASE_URL="postgres://user:pass@localhost/app"
export RYX_DB_REPLICA_URL="postgres://user:pass@localhost/app_replica"
RYX_DATABASE_URL becomes the default alias. RYX_DB_<ALIAS>_URL becomes the
lowercase alias name.
Config Filesโ
Ryx looks for the first existing file in the current directory:
ryx.yaml
ryx.yml
ryx.toml
ryx.json
Example ryx.toml:
[urls]
default = "postgres://user:pass@localhost/app"
replica = "postgres://user:pass@localhost/app_replica"
logs = "sqlite:///logs.db"
[pool]
max_conn = 10
min_conn = 1
connect_timeout = 30
idle_timeout = 600
max_lifetime = 1800
[models]
files = ["myapp.models", "billing.models"]
[migrations]
dir = "migrations"
The same structure can be represented as YAML or JSON.
Model-Level Database Aliasโ
Set Meta.database to bind a model to an alias by default:
class AuditLog(Model):
event = CharField(max_length=200)
class Meta:
table_name = "audit_logs"
database = "logs"
Reads and writes fall back to Meta.database unless .using() or a router
returns an alias first.
Query-Level Routingโ
Use .using(alias) for one query:
logs = await AuditLog.objects.using("logs").filter(event__icontains="login")
posts = await Post.objects.using("replica").filter(active=True)
Use .schema(schema) for PostgreSQL multi-schema queries:
tenant_posts = await Post.objects.schema("tenant_42").filter(active=True)
Global Routerโ
from ryx.router import BaseRouter, set_router
class ReadReplicaRouter(BaseRouter):
def db_for_read(self, model, **hints):
if getattr(model._meta, "database", None):
return model._meta.database
return "replica"
def db_for_write(self, model, **hints):
return getattr(model._meta, "database", None) or "default"
def allow_migrate(self, db, app_label, model_name):
return True
set_router(ReadReplicaRouter())
Router methods return an alias string or None. Returning None tells Ryx to
continue fallback resolution.
Resolution Orderโ
Read operations resolve aliases in this order:
- QuerySet
.using(alias) Router.db_for_read(model)Model.Meta.database"default"
Write operations resolve aliases in this order:
- Explicit
save(using=alias)or QuerySet.using(alias)where supported Router.db_for_write(model)Model.Meta.database"default"
Introspection Helpersโ
ryx.is_connected("default")
ryx.list_aliases()
ryx.pool_stats()
Use these helpers for startup diagnostics and health checks.
CLI Integrationโ
The CLI shares the same config discovery rules. For multi-database work:
python -m ryx migrate --models myapp.models --database default
python -m ryx makemigrations --models myapp.models --alias logs
Use --database for applying migrations to one alias. Use --alias when
generating alias-specific migration files.