Architecture
What runs where: web app, dataplane, StarRocks, Cube, n8n, Zitadel?
A standalone Vantage is one web app, one ingest service, a warehouse and a semantic layer,
with its own Zitadel, deployed as Nomad jobs on a Consul and Vault cluster
(vantage-deployment), or as one Docker Compose project on a laptop. n8n is not part of a
standalone deployment: the Nomad jobs and the compose file have none. Platform n8n exists
only when Vantage runs inside a Norims cluster; a workspace can still point at its own n8n,
Airbyte or OpenFN from Integrations.
What runs where
The picture shows Vantage inside a Norims cluster. norims-backend, its pack registry and the platform n8n come from Norims; a standalone deployment has none of them.
Hosts and ports
| Component | Job (Nomad) | Holds | Persistent |
|---|---|---|---|
| analytics-web | analytics-web | UI, server functions, control plane, OIDC sessions, MCP endpoint | no; state in Postgres |
| dataplane | dataplane | Uploads, batch loads, DDL, warehouse users, modeled datasets, the Temporal worker | no |
| StarRocks | starrocks (FE, BE), starrocks-bootstrap | Every workspace's data, one database each | starrocks-meta, starrocks-storage volumes |
| Cube | cube | Metrics REST API; pre-aggregations in a CubeStore sidecar | cubestore-data volume |
| Postgres | Cloud SQL (GCP) or the database host | analytics, zitadel, temporal, temporal_visibility | yes |
| Zitadel | zitadel, zitadel-login | Users, organisations (one per workspace), OIDC | in Postgres |
| Vault | systemd on control-plane nodes | Job secrets; per-workspace read-only credentials; dbt credential markers | Raft |
| Valkey | valkey | SQL editor budgets, Cube cache, MCP rate limits | valkey-data volume |
| RustFS | rustfs, rustfs-bootstrap | vantage-parquet-staging bucket | rustfs-data volume |
| Temporal | temporal | Ingestion schedules and runs | in Postgres |
| oauth2-proxy | oauth2-proxy | Sign-in gate for uploads., monitoring., logs. | no |
| backup | backup (periodic, 02:30 UTC) | Postgres dumps and the staging bucket, mirrored to B2 | backups volume |
| Observability | otel-collector, victoriametrics, victorialogs, perses, node-exporter | Metrics, logs, dashboards | volumes on the monitoring worker |
Consul, Vault and Nomad servers run on three control-plane nodes; jobs run on three workers. Each stateful job is pinned to the worker that carries its host volume, so a reschedule never restarts it on an empty disk.
Request paths
| Path | Hops |
|---|---|
| Sign-in | browser → auth.<d> (Zitadel, PKCE, no client secret) → analytics.<d>/auth/callback; the session is held server-side behind an encrypted __Host-sid cookie (8 hours) |
| Dashboard widget | browser → analytics-web server function → Cube REST with a JWT the server mints for the session's workspace → StarRocks as ro_<slug> |
| SQL editor | browser → analytics-web → StarRocks as the project's p_<project id> user, SELECT/WITH only, budget-checked in Valkey |
| File upload | browser asks analytics-web for a 5-minute ticket → posts the file to uploads.<d> → dataplane stages it in RustFS → StarRocks reads it with FILES() into raw_<source> |
| Scheduled sync | Temporal schedule → dataplane worker → the n8n workflow's webhook (N8N_WEBHOOK_URL) → the workflow reads cdc-plan, extracts, and posts batches to load-batch → stream load into the BE. A standalone cluster runs no n8n, so this needs one you provide |
| Cube schema | Cube → analytics-web /api/internal/cube/* with CUBE_SERVICE_TOKEN, per workspace |
| MCP | agent → analytics.<d>/api/mcp with a vmcp_ token → same server functions as the UI |
The browser never holds a Cube, StarRocks or Vault credential; everything data-bearing goes through analytics-web server functions, except the file upload, which carries only its ticket.
Tenant boundary
A workspace is a Zitadel organisation. Its id is the tenant_id everywhere: the
urn:zitadel:iam:user:resourceowner:id claim, the control-plane row key, the Cube security
context, and the tenant_id column on every warehouse row. Its slug names the warehouse
database (tenant_<slug>) and its StarRocks users. How each hop enforces it is
Tenant isolation.
Prod and preview on one cluster
| Shared | Per environment |
|---|---|
| Postgres server, Temporal server, StarRocks, RustFS, Valkey, oauth2-proxy, Caddy, Vault, Consul, backup, observability | databases (analytics / analytics_preview), Nomad namespace, Vault tree (secret/preview/…), bucket (…-preview), warehouse prefix (preview_tenant_<slug>), hostnames (*.preview.<d>), Zitadel, analytics-web, cube, dataplane |
Local compose
vantage-deployment/compose/vantage.sh runs the same services as the compose project
vantage, plus Mailpit for mail, without Caddy, oauth2-proxy, backup or observability. Ports
are in Deploy and upgrade.