Skip to content

Configuration Reference

All settings are read from environment variables (or a .env file in the working directory). No restart-free reloading — the server must be restarted for changes to take effect.


Database

Variable Default Description
DATABASE_URL postgresql+asyncpg://aimon:changeme@localhost:5431/aimonitoring Async SQLAlchemy connection string. Must use the +asyncpg driver suffix.
BASE_URL http://localhost:8000 Public base URL of the server (used in generated links).

Production credentials

The default password changeme triggers a startup warning. In production the server will refuse to start (ENVIRONMENT=production) unless DATABASE_URL is overridden with secure credentials.

Cloud SQL (Google Cloud)

When CLOUD_SQL_INSTANCE is set the server uses the Cloud SQL Python Connector instead of a direct TCP connection.

Variable Default Description
CLOUD_SQL_INSTANCE (unset) Cloud SQL instance connection name, e.g. project:region:instance. Setting this enables the connector.
CLOUD_SQL_DATABASE aimonitoring Database name inside the Cloud SQL instance.
CLOUD_SQL_USER (empty) Database user. Leave empty when using IAM authentication.
CLOUD_SQL_IP_TYPE public IP type used by the connector — public or private.
CLOUD_SQL_IAM_AUTH true Use IAM-based authentication (recommended). Set to false for password auth.

Dashboard performance

The dashboard computes distribution statistics (histograms, means, std, etc.) over the most-recent N inference records rather than all historical data. This keeps response times low regardless of how many records are stored.

Variable Default Description
DASHBOARD_MAX_SAMPLES 50000 Maximum inference rows used per dashboard panel. The most recent rows are selected so the view reflects current model behaviour. Counts and min/max in the response are always exact; distribution shape and mean/std are based on the sample (statistically representative at this size). Increase if you need higher precision; decrease to improve latency on slower hardware.

What is exact vs. sampled

When the time window contains more records than DASHBOARD_MAX_SAMPLES each panel includes a sample_info object:

{
  "sample_size": 50000,
  "total_count": 1800000,
  "is_sampled": true
}
Statistic Source Notes
total_count (record count) Exact — full population COUNT(*) Uses the (model_version_id, timestamp) index, no JSON read required.
min / max Sample Most-recent N records. Getting all-time exact min/max requires a full JSON-column scan (same cost as the unsampled query), which negates the performance gain. For monitoring, recent bounds are more meaningful than historical outliers.
mean, std, median Sample Statistically representative at 50k rows.
Histogram bucket counts Sample Shape is accurate; absolute counts reflect sample size. Buckets are 20 equal-width bins plus up to two outlier buckets (is_underflow / is_overflow in the API) for values below p1 / above p99, so up to 22 buckets are returned.
Category percentages Sample Ratios are unaffected by sample size.

Drift detection

Variable Default Description
DRIFT_MAX_SAMPLES 10000 Maximum inference or reference records loaded into memory for drift metric computation (KS, PSI, chi-squared). Statistical tests give reliable results well below this threshold. Increase for higher precision; at 10k the error vs. the true p-value is negligible for monitoring purposes.

Reference data

Variable Default Description
REFERENCE_DATA_MAX_RECORDS 50000 Hard cap on the number of records accepted in a single reference-data upload (POST …/reference-data). Requests exceeding this limit are rejected with HTTP 422. Uploading reference data is a replace operation — each successful upload replaces all previously stored reference records for that model version.

Choosing a reference set size

Statistical drift tests (KS, PSI, chi-squared) produce stable results with as few as 1 000 – 5 000 reference records. 50 000 is conservative. Very large reference sets increase drift-job memory usage without meaningfully improving detection accuracy.


Security and multi-instance operation

Variable Default Description
ENVIRONMENT development production / prod enforces secrets and disables the API docs by default.
AUTH_JWT_SECRET (none) JWT signing secret. Required in production -- the server refuses to start without it (ephemeral secret in development, sessions then do not survive restarts). Generate with openssl rand -base64 32.
SESSION_SECRET (none) Session/OAuth state secret. Required in production (ephemeral secret in development).
BOOTSTRAP_ADMIN_PASSWORD (generated) Initial admin password (min. 12 characters, otherwise the server refuses to start). Recommended for the first start and effectively required on Cloud Run, where you cannot read files inside an instance. If unset, a password is generated and written to BOOTSTRAP_ADMIN_PASSWORD_FILE.
BOOTSTRAP_ADMIN_PASSWORD_FILE ./admin-initial-password.txt New file (mode 0600, never overwritten) receiving the generated initial admin password, relative to the server's working directory. The password is never logged, only the file path. If the file cannot be created (not writable, or it already exists), the password is printed once to stderr -- in containers usually the log stream, so set BOOTSTRAP_ADMIN_PASSWORD or a writable path instead. The admin account is only created after the password has been delivered.
API_DOCS_ENABLED true / false in production Expose /docs, /redoc and /openapi.json.
SECURITY_HEADERS_ENABLED true Add CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy and HSTS (over HTTPS).
RATE_LIMIT_ENABLED true Enable rate limiting.
RATE_LIMIT_TRUSTED_PROXY_HOPS 0 Trusted reverse proxies in front of the server; 1 on Cloud Run accessed directly, typically 2 behind an external HTTPS load balancer. Client IP is the N-th X-Forwarded-For entry from the right (an external HTTPS load balancer sends X-Forwarded-For: <client>, <load-balancer-ip>); client-supplied entries on the left are ignored. Check the header your deployment actually receives. If unset behind a proxy, all users share one rate-limit bucket.
RATE_LIMIT_STORAGE_URI memory:// Rate limit storage backend, e.g. redis://host:6379 (the Redis client must be installed separately).
SCHEDULER_ENABLED true Run the drift job scheduler inside the API process. Set false on API instances when scheduled jobs run in the worker (python -m yaai.server.worker, which ignores this setting).

See Deployment for running more than one instance (worker, advisory lock, job reconciliation).


Environment file

Place a .env file in the directory where the server starts:

DATABASE_URL=postgresql+asyncpg://user:password@db-host:5432/aimonitoring
DASHBOARD_MAX_SAMPLES=100000
DRIFT_MAX_SAMPLES=20000
REFERENCE_DATA_MAX_RECORDS=50000

All variables are optional — unset variables use the defaults shown above.