chmonitorchmonitor
OperateAdvanced

Operate

Self-Hosted State Backends

Persist dashboards, per-user connections, and conversations in your own ClickHouse or Postgres instead of Cloudflare D1 — env vars and resolution order for Docker and Kubernetes deployments.

1 min read

Self-hosted (Docker / Kubernetes) deployments can persist UI-monitoring state — saved dashboards, per-user connections, and agent conversations — in a database you operate, instead of Cloudflare D1 (which only exists on the hosted Workers deployment). Without a backend, dashboards fall back to browser localStorage and conversations to memory.

ClickHouse

Reuse or dedicate an instance via CHM_STATE_CLICKHOUSE_*. Tables are created lazily (CREATE TABLE IF NOT EXISTS, ReplacingMergeTree) — no migrations.

Postgres

DATABASE_URL / POSTGRES_URL. Tables are also created lazily on first use. One string serves dashboards, connections, and conversations.

Resolution order

Each store resolves its backend at runtime, fail-open and OSS-first:

Loading diagram…

Per-user rows need auth

Server-side dashboard and connection storage also requires the per-user feature gates (CHM_FEATURE_CONVERSATION_DB / CHM_FEATURE_USER_CONNECTIONS_DB) and an auth provider — rows are keyed by user id. See Environment variables.

ClickHouse state backend

CHM_STATE_CLICKHOUSE_URL=http://clickhouse:8123

# Optional
CHM_STATE_CLICKHOUSE_USER=default          # default: default
CHM_STATE_CLICKHOUSE_PASSWORD=             # default: empty
CHM_STATE_CLICKHOUSE_DATABASE=chmonitor    # default: chmonitor
CHM_STATE_CLICKHOUSE_TABLE_PREFIX=chm_state_  # default: chm_state_

The user needs CREATE DATABASE / CREATE TABLE, INSERT, SELECT, and lightweight DELETE permissions on the state database. Tables (chm_state_dashboards, chm_state_user_connections) use ReplacingMergeTree(updated_at) with FINAL reads, so updates are plain inserts and no mutations are required for normal operation.

Monitoring users are often read-only

This can be the same ClickHouse you monitor, but a monitoring user is often read-only — point CHM_STATE_CLICKHOUSE_USER at a writable account (or a separate small instance) if so.

Postgres state backend

DATABASE_URL=postgres://user:pass@host:5432/chmonitor
# or POSTGRES_URL / POSTGRES_PRISMA_URL

One connection string serves all three stores (user_connections, dashboards, and the conversation tables).

On this page