Architecture
QuOptuna ships as a single Python package, src/quoptuna/, that bundles four cooperating layers: a core optimization engine (backend/), a FastAPI server (server/), a command-line interface (cli.py), and a pre-built Next.js static UI (web/). A legacy Streamlit dashboard (frontend/app.py) is also included as a fallback. This page explains how those pieces relate and how a request flows through them.
The layers
Section titled “The layers”The engine is the heart of the system: an Optuna wrapper that builds a search space, runs trials, scores them, and records results. It knows nothing about HTTP.
The server is a thin FastAPI application (quoptuna.server.main:app, titled “QuOptuna Next API”). It exposes REST routers, orchestrates runs as background tasks, and manages persistence. It also mounts the compiled Next.js UI at / and serves interactive API docs at /api/docs.
The web UI is a Next.js 15 / React 19 App Router application. The top-level frontend/ directory holds its dev source; make build_package runs npm run build and copies frontend/out into src/quoptuna/web, so a plain uvx quoptuna ships the fully-built UI.
The CLI drives the same engine headlessly for scripted or reproducible runs.
flowchart TD Browser["Browser (Next.js UI)"] -->|REST| API["FastAPI server"] CLI["CLI"] --> Engine["Optimization engine (Optuna)"] API --> Engine Engine --> Study[("Optuna study (SQLite in db/)")] API --> Stores[("run_store / analysis_store / dataset_registry")] API -->|mounts| BrowserPackaged vs dev mode
Section titled “Packaged vs dev mode”In packaged mode, one uvicorn process serves both the UI and the API on a single port (default 8000) — same origin, no CORS gymnastics for the user. This is what end users get from uvx quoptuna.
In dev mode, two processes run side by side: FastAPI on :8000 and the Next.js dev server on :3000. The server is CORS-enabled so the separate frontend origin can call it during development.
Request flow
Section titled “Request flow”Starting a run is asynchronous. The browser (or CLI) issues POST /api/v1/optimize, and the server launches the optimization as a FastAPI background task so the request returns immediately. The engine then writes trials into an Optuna study on disk. The UI polls GET /api/v1/optimize/{id}/trials for live progress rather than holding a long connection open.
Persistence model
Section titled “Persistence model”Three SQLite stores hold server-side state:
run_store— durable optimization-run records. On startup it marks any stalerunning/pendingruns asinterrupted, which enables crash rehydration: a restarted server can recover and reconcile in-flight work.analysis_store— analysis snapshots and reports (SHAP, confusion matrices, LLM reports).dataset_registry— maps eachdataset_idto its persisted CSV path.
These are distinct from the per-study Optuna SQLite files. The stores track orchestration and results metadata; the Optuna studies own the trial-level truth.
Auth model
Section titled “Auth model”Authentication is optional and handled by Auth0 (the auth0-server-python SDK). Sessions live in encrypted, httponly cookies — there is no server-side session store to manage. Enforcement is a no-op when the AUTH0_* environment variables are unset, so local, dev, and test runs work unauthenticated with zero configuration.