ClickHouse semantic layer

The ClickHouse semantic layer you define in TypeScript

Model your table once — tenant key, time key, typed fields — and every semantic query inherits it. Across your APIs, jobs, and dashboards. No YAML. No separate platform. No service to run.

Your semantic layer is a TypeScript file.

A dataset declares your table, its tenant key, its time key, dimensions, and measures — once. Semantic queries built on it carry tenant and time context automatically when runtime tenancy is active. Change the definition; downstream usage follows the same typed contract.

datasets/orders.ts

A semantic layer doesn't have to be a platform.

The standard answer to “ClickHouse semantic layer” is Cube or dbt MetricFlow — a separate service, modeled outside your application stack, run alongside your code. That is the right tool when centralized BI metrics for non-engineers is the job.

For a TypeScript team shipping product features, it is often the wrong shape. Your semantic layer should live in your codebase, your types, and your deploys. Datasets put it there: one definition, governed everywhere, without adopting a separate platform.

Multi-tenancy you can't forget.

The worst bug is the filter you forget to write. Declare tenantKey once on the dataset and semantic execution injects the tenant filter from runtime context. In Serve, require tenant context and requests without it fail before query execution.

TypeScript checks the fields, dimensions, measures, and filters you reference. Tenant identity itself is enforced at runtime because it comes from auth/request context.

tenant-scope.ts

One definition. Every consumer.

Compose query definitions around the dataset and serve them anywhere — the same definition feeds server code, a typed HTTP route, and a React hook, with types intact across the network.

analytics/revenue-by-day.ts
consumers.ts

hypequery vs Cube / dbt MetricFlow

Both shapes can be correct. The question is whether you want a TypeScript semantic layer inside your product codebase, or a separate metrics platform for centralized BI.

Lives in

Where the semantic layer physically runs

hypequeryYour TypeScript codebase
Cube / MetricFlowSeparate service / platform
Language

How you author metrics and dimensions

hypequeryTypeScript
Cube / MetricFlowYAML / modeling DSLs
Types

Compile-time safety from schema to response

hypequeryEnd-to-end TypeScript contracts
Cube / MetricFlowLimited or external to app code
Tenancy

How rows are isolated per tenant

hypequeryRuntime-enforced from tenant context; typed fields
Cube / MetricFlowManual filters or platform policy
Operate

What you deploy and maintain in production

hypequeryA library in your stack
Cube / MetricFlowA platform to run
Best for

The workload each shape fits

hypequeryShipping ClickHouse-backed product features
Cube / MetricFlowCentralized BI metrics and non-engineer consumers
BI Support

Fit for dashboards and self-serve BI tools

hypequeryNot a full BI modeling platform
Cube / MetricFlowBetter fit for broad BI governance

Next step

Define your first dataset in 30 seconds.

npx @hypequery/cli init