ClickHouse
Production-grade OLAP AnalyticsSink over ClickHouse — self-hosted or ClickHouse Cloud — for billions of events with millisecond aggregates.
@voltro/plugin-clickhouse is the production AnalyticsSink for analytics at
scale — native HTTP ingest into a ClickHouse cluster (self-hosted or
ClickHouse Cloud, both via the official @clickhouse/client). The sink owns an
events table inside the configured database (a MergeTree engine created on
first boot) and implements all four contract methods. Reach for it when
postgres-lite hits its ~10M events/day
ceiling and you need millisecond aggregate queries over billions of rows. For
the shared AnalyticsSink API and the useAnalytics() read methods, see
Analytics & warehouse sinks.
Install
pnpm add @voltro/plugin-clickhouseWiring
// app.config.ts
import { clickhouseAnalytics } from '@voltro/plugin-clickhouse'
export default {
type: 'api' as const,
name: 'myApi',
store: 'postgres' as const,
analytics: clickhouseAnalytics({
url: process.env.CLICKHOUSE_URL!, // https://my-cluster.clickhouse.cloud
username: process.env.CLICKHOUSE_USER,
password: process.env.CLICKHOUSE_PASSWORD,
database: 'voltro_events', // optional, default 'default'
}),
}At boot the plugin opens the client, pings the cluster (fail-fast on bad config), and creates the events table + any mirror tables. The client is closed on graceful shutdown.
Options
clickhouseAnalytics(options):
| Option | Type | Default | Notes |
|---|---|---|---|
url |
string |
— (required) | HTTP URL of the ClickHouse server, incl. protocol + port. |
username |
string |
— | |
password |
string |
— | |
database |
string |
'default' |
The plugin creates the events table inside it on first boot. |
table |
string |
'events' |
Override the events-table name. |
mirrorTables |
ReadonlyArray<string> |
[] (events-only) |
Reactive tables to CDC-mirror into voltro_mirror_<table> (a ReplacingMergeTree) so analytical queries JOIN events against live user data. |
mirrorPrimaryKey |
string |
'id' |
Primary-key column on the mirrored source rows. |
database, table, and each mirrorTables entry are validated as SQL
identifiers at boot (they're interpolated into DDL) — a bad name fails loudly at
app.config eval, not on the first query.
Connection details come from
options, not env. The plugin reads noCLICKHOUSE_*variables itself — the example above wiresprocess.envinto the options. Use@voltro/env'sdefineEnvto declare them as secrets.
No raw-client escape hatch
ClickHouse-specific features outside the cross-provider contract
(HyperLogLog, dictionaries, materialised views) are not reachable through
the plugin — it exposes no raw @clickhouse/client handle; the
AnalyticsSink contract is the extension seam. Where you need them, query
ClickHouse with your own client instance against the same tables.
Using the Tag binds your handler to ClickHouse — stay on useAnalytics() for
provider-portable code. The plugin also exports EVENTS_TABLE_DDL and
MIRROR_TABLE_DDL for advanced schema work.
See also
- Analytics & warehouse sinks — the shared
AnalyticsSinkcontract, theuseAnalytics()read API,composeAnalytics, and the CDC-mirror details.