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_passwordInstall
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-credentialsThe 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-credentialsclickhouse.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:
| Value | Default |
|---|---|
autoscaling.minReplicas | 2 |
autoscaling.maxReplicas | 10 |
autoscaling.targetCPUUtilizationPercentage | 70 |
autoscaling.targetMemoryUtilizationPercentage | 80 |
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 migrateFor 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.jsProduction charts default MIGRATE_ON_START to false so every replica does not attempt schema migration on startup.