ClickHouse Product Analytics
Deployment

Helm

Install the ingest service on Kubernetes with autoscaling.

The Helm chart in deploy/helm/clickhouse-product-analytics deploys the ingest service to Kubernetes. It does not deploy ClickHouse. Point it at ClickHouse Cloud or an existing in-cluster ClickHouse service.

Render Locally

helm template cpa ./deploy/helm/clickhouse-product-analytics \
  --set ingest.publicApiKeys=local_dev_key \
  --set clickhouse.url=http://clickhouse:8123 \
  --set clickhouse.user=analytics \
  --set clickhouse.password=local_dev_password

Install

helm upgrade --install cpa ./deploy/helm/clickhouse-product-analytics \
  --namespace analytics \
  --create-namespace \
  --set image.repository=ghcr.io/marcklingen/clickhouse-product-analytics/ingest-service \
  --set image.tag=sha-<commit> \
  --set ingest.publicApiKeys="<backend-key-old>,<backend-key-new>" \
  --set ingest.allowedOrigins="https://app.example.com" \
  --set clickhouse.url="https://<clickhouse-cloud-host>:8443" \
  --set clickhouse.database="product_analytics" \
  --set clickhouse.user="<user>" \
  --set clickhouse.password="<password>"

Use an existing Kubernetes secret for ClickHouse credentials when possible:

helm upgrade --install cpa ./deploy/helm/clickhouse-product-analytics \
  --set ingest.publicApiKeys="<backend-key-old>,<backend-key-new>" \
  --set clickhouse.url="https://<clickhouse-cloud-host>:8443" \
  --set clickhouse.existingSecret=clickhouse-credentials

The existing secret must contain keys named username and password unless you override clickhouse.existingSecretUserKey and clickhouse.existingSecretPasswordKey.

Use image.tag=latest only for quick trials. Production rollouts should use a sha-<commit> tag or a digest-pinned image:

helm upgrade --install cpa ./deploy/helm/clickhouse-product-analytics \
  --set image.repository=ghcr.io/marcklingen/clickhouse-product-analytics/ingest-service \
  --set image.digest=sha256:<digest> \
  --set ingest.publicApiKeys="<backend-key-old>,<backend-key-new>" \
  --set clickhouse.url="https://<clickhouse-cloud-host>:8443" \
  --set clickhouse.existingSecret=clickhouse-credentials

clickhouse.url is required. Rendering fails early when it is missing so an invalid deployment is not applied. Set ingest.publicApiKeys to a comma-separated list when backend or no-origin ingest is enabled; browser-only deployments that rely on ingest.allowedOrigins can omit API keys.

Autoscaling Defaults

Autoscaling is enabled by default:

ValueDefault
autoscaling.minReplicas2
autoscaling.maxReplicas10
autoscaling.targetCPUUtilizationPercentage70
autoscaling.targetMemoryUtilizationPercentage80

The chart also sets resource requests and limits so the HPA has stable utilization signals. Tune these values after observing real traffic and ClickHouse insert latency.

Migrations

Run migrations from a checkout before deploying a new schema:

CLICKHOUSE_URL="https://<clickhouse-cloud-host>:8443" \
CLICKHOUSE_USER="<user>" \
CLICKHOUSE_PASSWORD="<password>" \
CLICKHOUSE_DATABASE="product_analytics" \
npm run migrate

For a Kubernetes-only network path, run a one-off pod or job with the same image and environment variables, then execute the compiled migration entrypoint from the image:

CLICKHOUSE_URL="https://<clickhouse-cloud-host>:8443" \
CLICKHOUSE_USER="<user>" \
CLICKHOUSE_PASSWORD="<password>" \
CLICKHOUSE_DATABASE="product_analytics" \
node dist/migrate.js

Production charts default MIGRATE_ON_START to false so every replica does not attempt schema migration on startup.

On this page