Self-hosting Architecture
Provon separates product responsibilities into logical planes even when one runtime co-locates them. This keeps storage, scaling, and security decisions explicit without requiring
On this page Browse sections
Logical Planes#
flowchart LR
users["Users"] --> workbench["Workbench"]
apps["Agent applications"] --> gateway["Gateway"]
apps --> otlp["OTLP ingest"]
workbench --> api["Control API"]
gateway --> providers["Model providers"]
gateway --> evidence["Evidence pipeline"]
otlp --> evidence
api --> meta["Metadata store"]
evidence --> blobs["Blob / staging store"]
evidence --> telemetry["Telemetry store"]
evidence --> jobs["Background execution"]
jobs --> telemetry
jobs --> meta
jobs --> connectors["External connectors"]| Plane | Responsibilities |
|---|---|
| Workbench | User-facing configuration, trace investigation, Findings, and operations |
| Control API | Identity, organizations, projects, API keys, provider settings, Rules, and connectors |
| Request data plane | Gateway request policy, provider routing, guardrails, OTLP acceptance, and staging |
| Background execution | Ingest decoding, trace summaries, workflows, diagnostics, retention, and status sync |
| Storage | Metadata, telemetry, blobs, queue state, and runtime state |
The planes are logical ownership boundaries. Node runs them in one process. Cloudflare maps them to separate deployable surfaces and managed services.
Node Mapping#
reverse proxy
-> node-server
-> Workbench + API + Gateway + OTLP
-> in-process background loops
-> libSQL/SQLite metadata
-> DuckDB or MotherDuck telemetry
-> local blobs and persistent runtime stateThe Node entrypoint is services/node-server. It composes the shared API and Node runtime, applies
metadata migrations at startup, serves the built Workbench, and starts local background loops.
Node is intentionally a single-instance architecture with the default adapters:
- metadata can be local SQLite or remote libSQL;
- telemetry can be local DuckDB or MotherDuck;
- blobs, ingest queues, Gateway telemetry queues, summary queues, and other runtime state remain in the configured local data directory;
- local model process lifecycle is owned by the Node runtime.
Remote metadata or telemetry alone does not make the runtime horizontally scalable. Multiple active processes would have independent local queues and duplicate schedulers.
Cloudflare Mapping#
Cloudflare Pages -> Workbench
API Worker -> identity, control API, reads
Gateway Worker -> model traffic and policy
OTLP Worker -> ingest acceptance and staging
Jobs Worker -> queue consumers and scheduled work
Warehouse Worker -> organization-routed telemetry mutations
Container -> Iceberg table writes and retention deletes
D1 -> metadata
KV -> Gateway runtime cache
Queues -> ingest, summaries, and workflow jobs
Durable Objects -> Gateway usage and target state
R2 -> blobs, staged payloads, and Iceberg data
R2 SQL -> telemetry readsThe split runtime keeps hot request paths independent:
- Workbench availability does not sit on the Gateway request path.
- OTLP acceptance can queue work before telemetry projection completes.
- the Jobs Worker owns queue consumption, diagnostics, summaries, retention, and scheduled maintenance;
- telemetry mutation runs behind an internal Service Binding and organization-scoped warehouse execution.
All resources live in the operator's Cloudflare account. There is no Provon-hosted administration plane that must be reachable for the deployment to function.
Request And Data Flow#
Gateway Request#
- The application authenticates with a project API key.
- Gateway loads project routing, provider, usage, and guardrail policy.
- Gateway decrypts the selected project provider credential inside the runtime.
- The request is sent to the selected model provider.
- The response returns through Gateway while trace evidence is queued.
- Background processing projects the evidence into telemetry and updates derived summaries.
Prompts and responses leave the deployment when the selected provider is external. A private Provon deployment does not make an external model provider private.
OTLP Ingest#
- The exporter sends OTLP/HTTP with a project API key.
- Provon validates authentication, body size, and signal support.
- The accepted payload is staged and queued.
- A worker decodes, normalizes, and writes spans, logs, or metrics.
- Trace summaries become visible and can trigger workflows or diagnostic Rules.
Acceptance and visibility are asynchronous. A successful ingest response proves durable acceptance for that runtime; trace visibility is a separate verification gate.
Control And Connector Flow#
Workbench sessions call the Control API. Provider keys, connector credentials, and OAuth tokens are encrypted before they are stored in metadata. Connector actions and OAuth handshakes create outbound requests to the configured external systems.
Storage Boundaries#
| Data class | Contents | Node | Cloudflare |
|---|---|---|---|
| Metadata | Users, projects, keys, Rules, Findings, settings, encrypted secrets | SQLite/libSQL | D1 |
| Telemetry | Spans, logs, metrics, summaries, usage, and diagnostic evidence | DuckDB or MotherDuck | R2 Data Catalog / Iceberg, R2 SQL |
| Blobs | OTLP staging, attachments, exports, and large payloads | Local filesystem | R2 |
| Runtime state | Ingest jobs, summary work, Gateway telemetry, and local leases | Persistent local files | Queues, D1, KV, Durable Objects |
| Local model artifacts | Models, engines, process state, and health | Local filesystem and process | Not provided |
Back up metadata independently from telemetry. Metadata contains the tenant model and encrypted credentials; telemetry contains the evidence those records reference. Restoring only one can leave links incomplete even when both stores are individually valid.
Network Boundary#
Required inbound paths depend on enabled features:
| Caller | Surface |
|---|---|
| Browser | Workbench and authentication callbacks |
| Agent application | /gateway/v1/* |
| OTel exporter | /v1/traces, /v1/logs, /v1/metrics |
| Automation client | /v1/* API routes allowed by its project key |
Potential outbound paths include:
- configured model providers;
- sign-in identity providers;
- Connector OAuth and API endpoints;
- MotherDuck when selected by the Node runtime;
- package registries and Cloudflare APIs during build or deployment.
The core runtime can remain on a private network when all callers are private, model execution is local, and external identity and connectors are disabled. Document each enabled egress dependency instead of assuming an air-gapped deployment.
Failure Boundaries#
| Failure | Expected effect |
|---|---|
| Workbench unavailable | API, Gateway, and OTLP may continue if their runtime surfaces are healthy |
| Model provider unavailable | Gateway request fails or follows configured retry/fallback policy |
| Telemetry writer delayed | Accepted evidence remains queued; trace visibility lags |
| Metadata unavailable | Sign-in, project lookup, policy, and most control operations fail |
| Background execution stopped | Ingest projection, summaries, diagnostics, retention, and status sync lag |
| Blob storage unavailable | New staged ingest and attachment operations fail |
Design health checks and alerts around these boundaries. /healthz reports runtime liveness and
version; it is not a complete dependency or end-to-end evidence check.