Overview

ClickStack

The design idea underneath it: all observability data is ingested as wide, rich events. Events are stored in ClickHouse tables by type, and stay fully queryable and cross-correlatable at the database level.

The three components#

Component Role
HyperDX The UI — search, dashboards, alerting, and session replay
OpenTelemetry collector A preconfigured collector with an opinionated schema for logs, traces, and metrics
ClickHouse The analytical database storing and querying everything

The open-source distribution also uses MongoDB for application state: dashboards, alerts, user profiles, and saved visualizations.

Start the whole stack#

One container runs the collector, the UI, and ClickHouse together:

docker run --name clickstack \
  -p 8123:8123 -p 8080:8080 -p 4317:4317 -p 4318:4318 \
  clickhouse/clickstack-all-in-one:latest clickstack
Port Service
8080 HyperDX UI
4317 OTLP gRPC ingestion
4318 OTLP HTTP ingestion
8123 ClickHouse HTTP interface

Point any OpenTelemetry SDK or collector at port 4317 or 4318 and the data appears in the UI.

To keep data across container restarts, mount volumes for the databases:

docker run --name clickstack \
  -p 8123:8123 -p 8080:8080 -p 4317:4317 -p 4318:4318 \
  -v "$(pwd)/.volumes/db:/data/db" \
  -v "$(pwd)/.volumes/ch_data:/var/lib/clickhouse" \
  -v "$(pwd)/.volumes/ch_logs:/var/log/clickhouse-server" \
  clickhouse/clickstack-all-in-one:latest

ClickStack images are published as clickhouse/clickstack-*, replacing the earlier docker.hyperdx.io/hyperdx/* names.

Why ClickHouse underneath#

Observability data is high-volume, high-cardinality, and semi-structured — which is what ClickHouse is built for:

  • Compression rates of at least 10x on observability data.
  • Sub-second search across terabytes of events.
  • Ingestion of billions of high-cardinality records per day.
  • Native support for semi-structured JSON, allowing schemas to evolve without migration.

Because storage is ordinary ClickHouse tables, your telemetry is queryable with SQL. Anything the UI does not offer, you can write a query for. See the JSON type for how dynamic event fields are stored columnar.

Updated

Was this page helpful?