Self-hosting Operations
Operate Provon as an evidence system, not only as an HTTP service. Runtime liveness, ingest acceptance, telemetry visibility, diagnostic execution, and external repair status are separate health signals.
Define Service Objectives#
Set explicit targets for:
| Signal | Example objective to define |
|---|---|
| Workbench and API | Availability and interactive latency |
| Gateway | Added latency, error rate, streaming success, and timeout rate |
| OTLP acceptance | Accepted requests, rejected bodies, and admission saturation |
| Evidence visibility | Time from acceptance to queryable trace |
| Diagnostic execution | Time from quiet conversation to completed Run |
| Queue and job processing | Oldest pending age, retries, and dead letters |
| Repair status | Time from external PR or Issue change to Finding update |
| Retention | Time from expiry to physical deletion |
Derive alert thresholds and capacity from these targets; do not infer them from default polling intervals.
Health Checks#
Public request-facing deployments expose GET /healthz with runtime status, version, and
deployment target:
curl --fail --silent https://provon.example.com/healthzUse it for the Node process and the API, Gateway, MCP, and OTLP Workers. Background-only
deployments differ: the telemetry pipeline, diagnostics, and maintenance Workers return a
plain healthz: ok response, and the warehouse Worker exposes GET /health.
Health checks do not prove that metadata queries work, telemetry can be written or read, queues are draining, a model provider is reachable, diagnostics are completing, or a Connector can perform its external action. Add synthetic checks with a dedicated project:
- Query an authenticated API endpoint.
- Send a small OTLP trace with a unique trace ID.
- Poll until the trace is queryable within the evidence-visibility objective.
- Send a low-cost Gateway canary and correlate
x-provon-request-idto its trace. - Periodically run a deterministic diagnostic Rule over known evidence.
Keep synthetic data clearly labeled and outside production diagnostic inputs when possible.
Monitor The Pipeline#
Node#
Capture stdout and stderr from the Node process. Alert on repeated error labels for:
[ingest-worker];[gateway-telemetry-worker];[telemetry-summary-materialization];[diagnostics];[finding-work-item-sync];[data-retention];[meta-store-maintenance];[gateway-usage-reconciliation].
Also monitor process restarts, filesystem free space, file-descriptor usage, memory, CPU, and DuckDB query latency.
Cloudflare#
Monitor each deployment independently:
- API, Gateway, OTLP, MCP, pipeline, diagnostics, and maintenance Worker errors;
- Queue backlog, oldest message age, retry exhaustion, and the ingest DLQ;
- Maintenance cron trigger success;
- Container starts, failures, and write latency;
- R2 SQL query errors;
- Data Catalog append, compaction, snapshot-expiration, and retention failures;
- D1, R2, KV, Durable Object, Worker, Queue, and Container usage.
A healthy API Worker can coexist with a stalled background Worker. Alert on the oldest unfinished work, not only on request error rates.
Back Up The Recovery Set#
Define one coordinated recovery point that includes:
- Metadata;
- Telemetry;
- Blobs and staged payloads;
- Persistent queue or runtime state;
PROVON_AUTH_SECRETand required storage credentials;- Deployment configuration and application version.
Store the secret recovery copy separately from encrypted metadata, and test restoration in an isolated environment on a schedule.
Node Backup#
For local SQLite and DuckDB, use a quiesced backup:
- Stop new Gateway and OTLP traffic at the ingress.
- Allow in-flight requests and background work to finish.
- Send
SIGTERMand wait for graceful shutdown. - Snapshot the complete persistent data directory.
- Record the Provon version and configuration revision.
- Restart and run the normal verification checks.
Include:
- the file behind
PROVON_META_DB_URL; - the file behind
PROVON_METERING_DB_URL; - the file behind
PROVON_GATEWAY_DB_URL; - the file behind
PROVON_JOBS_DB_URLwhen queued work should survive the restore; it holds only in-flight background jobs, so restoring without it loses queued work and nothing else; - the DuckDB file when local;
PROVON_BLOBS_DIRand its parent runtime-state files.
Use the libSQL provider's consistent export or snapshot mechanism for remote metadata and usage-event stores. Do not copy a live DuckDB file from storage with uncertain snapshot semantics.
Cloudflare Backup#
Treat each managed service according to its recovery model:
- export D1 metadata and usage events before upgrades and test D1 point-in-time recovery procedures;
- retain the Wrangler configs, Durable Object migration history, and resource IDs;
- protect R2 blobs and the Data Catalog bucket with account-level access and lifecycle policy;
- preserve Data Catalog maintenance settings;
- record Queue and DLQ state expectations in the recovery plan;
- keep deployment and secret inventory outside the Cloudflare account for account-recovery events.
Create a pre-upgrade D1 export:
pnpm exec wrangler d1 export provon-demo-meta \
--remote \
--output provon-demo-meta-pre-upgrade.sql \
--config services/cloudflare/wrangler.api.toml
pnpm exec wrangler d1 export provon-demo-metering \
--remote \
--output provon-demo-metering-pre-upgrade.sql \
--config services/cloudflare/wrangler.maintenance.tomlR2 Data Catalog tables are transactionally managed Iceberg data. Do not manually delete or rewrite catalog objects as a backup or cleanup method; doing so can leave table metadata inconsistent.
Restore#
Restore into an isolated origin first:
- Restore metadata with the original
PROVON_AUTH_SECRET. - Restore usage events to the matching recovery point.
- Restore telemetry and blobs to the matching recovery point.
- Restore Node runtime state or recreate Cloudflare bindings and queues.
- Start the same application version that created the backup.
- Verify sign-in, project membership, API keys, stored provider credentials, traces, Findings, and Connector decryption.
- Upgrade only after the recovered version is healthy.
- Switch traffic after the end-to-end synthetic checks pass.
If only metadata is restored, trace and attachment references may be missing. If only telemetry is restored, tenant ownership and access records may be missing. Document which degraded restore modes are acceptable.
Upgrade Node#
Use an immutable release or container tag.
- Read release and migration notes.
- Build the new Node image or source artifact.
- Run the Node server tests and relevant workspace checks.
- Quiesce traffic and create the recovery set.
- Stop the old process gracefully.
- Start one new process against the persistent data.
- Let startup migrations complete.
- Verify health, sign-in, API, OTLP, Gateway, traces, diagnostics, and Connectors.
- Retain the prior artifact until the release is accepted.
Do not run old and new Node processes concurrently against one local data directory during a rolling upgrade.
Upgrade Cloudflare#
- Read release and migration notes.
- Run
pnpm test:cf. - Export D1 metadata and usage events.
- Apply any required Data Catalog maintenance change.
- Run
pnpm release:build && pnpm release:check && pnpm release:publish. - Verify each deployment and the complete asynchronous evidence path.
- Watch queue lag, D1 errors, warehouse writes, and R2 SQL reads through the rollout window.
Application publishing does not run D1 initialization; prepare the current baseline
explicitly with pnpm release:db-init --remote. The project keeps only the current
initialization baseline: no historical data migrations, old schema compatibility, or release
aliases are maintained. Application rollback does not restore D1, R2, Queue, or Durable Object
state; preserve an isolated recovery copy before any live schema change and verify recovery
separately.
Capacity And Scaling#
Node#
Scale vertically and control evidence volume: CPU and memory for request handling and DuckDB queries; disk capacity and IOPS for metadata, telemetry, blobs, and queues; body and batch limits for ingest; trace capture and payload retention; and background loop batch sizes. When one process no longer meets availability or throughput objectives, move to shared adapter infrastructure or the Cloudflare runtime. Starting more default Node replicas creates independent local work queues and schedulers.
Cloudflare#
Scale each constrained service: Gateway Worker concurrency and provider deadlines; OTLP admission and Queue backlog; consumer concurrency and batch size; warehouse Container instances and append coalescing; R2 SQL read latency and summary freshness; D1 and Durable Object hot keys; Data Catalog small-file count and compaction. Tune from platform telemetry; raising producer admission without increasing consumer and warehouse capacity only moves the bottleneck into queue age.
Retention Operations#
Verify three mechanisms independently:
| Mechanism | Scope |
|---|---|
| Project telemetry retention | Expired telemetry rows and files |
| Raw payload retention | Prompt, response, and raw OTLP payload representation |
| Platform lifecycle maintenance | Staged objects, Iceberg snapshots, and compaction |
Retention is not backup expiration: keep recovery copies under a separate policy and document when they are destroyed.
On Cloudflare, retention runs inside the Maintenance Worker cron trigger (0 */6 * * *, every
six hours) alongside metadata maintenance and work-item sync. On Node, the retention job runs
on the interval set by PROVON_DATA_RETENTION_INTERVAL_MS (default six hours).
Run the maintenance configuration in dry-run mode after changes:
pnpm configure:cf:telemetry-maintenanceDefaults behind the script: OTLP and Gateway staging objects expire after 7 days; Data Catalog snapshot expiration keeps at least a 15-day window (required for queue-replay idempotency) and retains the last 10 snapshots; compaction targets 64 MB files. Do not shorten the snapshot window independently.
Incident Procedures#
Gateway Incident#
- Preserve
x-provon-request-idand the failing request shape. - Pause affected project traffic or route the application back to its prior provider endpoint.
- Check provider attempts, guardrail events, and usage reservations.
- Keep captured evidence for diagnosis.
Ingest Backlog#
- Separate acceptance errors from post-acceptance visibility lag.
- Measure oldest pending work and dependency errors.
- Stop increasing admission limits.
- Restore the writer, telemetry store, or queue consumer.
- Verify replay and deduplication before clearing dead letters.
Credential Exposure#
- Revoke the exposed workload, provider, Connector, storage, or deployment credential at its authority.
- Disable the affected integration or project path.
- Search logs and trace evidence for accidental secret capture.
- Replace the credential and verify the new path.
- Treat
PROVON_AUTH_SECRETexposure as deployment-wide encrypted-credential exposure and plan a full credential reauthorization or re-encryption event.
Storage Recovery#
- Stop writes.
- Preserve the current failed state for investigation.
- Restore into an isolated environment.
- Validate tenant ownership and cross-store references.
- Resume traffic only after end-to-end checks pass.
Release Gate#
- Recovery set and restore procedure are current.
- Health, queue, background job, storage, and provider alerts are active.
- Synthetic API, OTLP, and Gateway checks pass.
- The new version and config revision are recorded.
- Current initialization baseline prepared explicitly before the first release.
- Evidence visibility and diagnostic latency remain within objectives.
- Retention and Data Catalog maintenance completed successfully.
- The previous artifact and rollback procedure remain available.