Deployment topology
Understand where Studio, the API, DLM and Engine run after installation, how requests cross the trust boundary, and what must pass before a hosting cutover.
Topology
kaveon-aks inkaveon-rg, with a coordinator, autoscaled worker pool, API and DLM deployed as one PostgreSQL-free Helm release. Vercel hosts the Studio separately. The VM is a legacy migration reference only; useInstall & deploy and the automated AKS workflow for new deployments.Browser ──► Vercel (Kaveon Studio · Auth.js: GitHub / Google / Microsoft)
│ same-origin /api/kaveon proxy (injects X-User-* + secret)
▼
AKS private services ── TLS ──► API + DLM (FastAPI)
│
├──► Kaveon Engine coordinator ──► worker-1, worker-2
│ planning, cube and statistics fragment execution
│ Arrow exchange
▼
ADLS Gen2 · kaveonlake
├── opensource/snapshots/… Delta tables — the rows
└── product/kaveon/system/v2 KaveonDB — the platform's recordsThe browser only talks to Studio. The proxy forwards to the API with X-User-* headers stamped by KAVEON_PROXY_SECRET, which the API validates (see Auth & RBAC). The Engine’s own ports are bound to localhost on the VM and are never reachable from outside it.
Local Docker uses the repository’s docker-compose.yml for development; AKS uses the production Helm release. Datasets, charts, dashboards, saved statements, chat history and audit entries are transactional rows in kaveon.product.*, written only through KaveonDB’s transaction boundary; the table data itself is Delta in object storage, read in place.
Where state lives, and what a new host gets back
Three places, and only two of them are in object storage. This is the thing to know before you replace the machine.
| What | Where | Survives a new host |
|---|---|---|
| Table data | kaveonlake / opensource | Yes — object storage |
| The platform’s records: datasets, charts, dashboards, saved statements, chat history, favourites, audit | kaveonlake / product / kaveon/system/v2 | Yes — object storage |
| The Engine’s catalog: catalogs, schemas, every table definition, planner statistics, cubes | /var/lib/kaveon/catalog.db on the coordinator (the catalog-data volume) | No — a file on the host |
catalog.db alongside the system store, and see Operations for the sequence that rebuilds the catalog when you do not have it. Folding this third place into the first two is a design in progress.Where a query actually runs
A chart or a question reaches the Engine, and the Engine decides between two lanes. A cube-shaped aggregate is answered from precomputed cells and HyperLogLog sketches without reading the table; anything else is planned into fragments and executed across the workers with Arrow exchange, retry and cancellation. The Engine reports which lane it took on every statement, and Studio shows it. See Kaveon Engine for the execution model and Freshness for when a precomputed answer is allowed to stand.
CI/CD
.github/workflows/ci.yml runs on every push and PR to dev: type-check and build Studio, run the API test suite, run the operational script tests, scan for secrets, and validate the documentation. The documentation gate fails closed — a new Engine setting without a row in the settings table turns CI red and holds the Studio deploy with it. On a green run, Studio deploys to Vercel.
AKS deployment is explicit and environment-gated. The.github/workflows/deploy-aks-platform.yml workflow invokesscripts/deploy-kaveon-aks.sh with Azure OIDC. It checks immutable images, workload identity, Engine CA, ADLS, auth credentials and retirement evidence before an atomic Helm rollout. The retired Container Apps workflow is not used for new releases.
Running the whole platform locally
scripts/kaveon-up.sh brings up the same stack on any machine with Docker, generating its secrets once and writing them to .env. Point it at a directory of Delta or Parquet tables to mount read-only; the one decision worth making is where Kaveon keeps its own records. See Quickstart for the short path and the self-hosting guide for the long one.
./scripts/kaveon-up.sh --data /mnt/warehouse
./scripts/kaveon-up.sh --storage adls://myaccount/product/kaveon/system
# Studio: http://localhost:3000
# API: http://localhost:8082/api/health
# Engine: http://localhost:8081/v1/statementOnly Studio’s port is meant for a person. The API and the Engine publish to loopback so that Studio stays the only front door, which is what the proxy secret assumes.
docker-compose.workers.yml adds two more workers. It exists for one reason: the statistics and cube pass gives each worker a single task over all of its files, and that task has a hard 600 second ceiling, so a large table can only be cubed by putting fewer files in each task. Use it to build, then take the extra workers down — see the warning in that file before serving from it.
Key environment variables
| Where | Vars |
|---|---|
| Both tiers | KAVEON_PROXY_SECRET (must match) |
| Studio (Vercel) | AUTH_SECRET, AUTH_URL, provider IDs and secrets, API_URL, AUTH_ADMIN_EMAILS |
| API (AKS) | KAVEON_PROXY_SECRET, KAVEON_ENGINE_BRIDGE_TOKEN, KAVEON_ENGINE_CATALOG_TOKEN, KAVEON_CREDENTIAL_KEYS, KAVEON_CREDENTIAL_ACTIVE_KEY, workload identity and retirement evidence |
| The system store (coordinator and API, same values) | KAVEON_PRODUCT_STORAGE_MODE, and for object storage KAVEON_PRODUCT_ADLS_ACCOUNT, KAVEON_PRODUCT_ADLS_CONTAINER, KAVEON_PRODUCT_ADLS_PREFIX; for a directory KAVEON_PRODUCT_LOCAL_PATH |
| Engine (coordinator and workers) | KAVEON_DATA_DIR, KAVEON_EXCHANGE_TOKEN, KAVEON_DISCOVERY_URI, memory and spill settings |
The coordinator and the API read the system-store variables from the same values, so Settings can report where the control plane is kept without being told twice. The API only reads them; it never writes to that store.
Production notes
The AKS release separates the API from the coordinator and worker pool, uses private service networking, keeps opaque credentials in Key Vault, and uses workload identity for Azure resources. The deployment script refuses a PostgreSQL-backed render in either supported cutover mode.