ClickHouse SaaS Analytics

Embed customer-facing analytics in your SaaS product with ClickHouse

This is the point where analytics becomes product surface, not just internal reporting. You need tenant scoping that is hard to bypass, a stable API for the UI, and one query path that can serve dashboards, exports, and internal support views without splitting into separate implementations.

Tenant isolation

Enforced in context

Delivery

REST API + React hooks

Best for

Customer-facing SaaS analytics

Tenant scoping fails quietly when it is copied by hand

If every query author has to remember the tenant filter, somebody eventually forgets it. That is not a style issue. It is a product risk.

Customer-facing analytics grows more consumers than expected

The same usage metric often ends up on the customer dashboard, in support tooling, in exports, and inside internal admin screens. Separate implementations for each surface do not stay aligned for long.

The API layer becomes a product of its own

Once auth, validation, tenancy, and response typing are all hand-built around ClickHouse, teams accidentally sign up to maintain an analytics platform inside the app.

The safe default

Put tenant context in the standard request path

The useful move here is centralization. Put auth and tenant lookup in the request context, make every query read from that context, and keep the customer-facing API surface tied to those shared definitions.

  • Tenant ID injected per-request from JWT, API key, or session
  • Every query in the serve() call has access to typed tenant context
  • Tenant scoping lives in one reviewable path instead of every query file
  • The same query definition can serve dashboard, API, export, and report use cases
  • React hooks consume typed endpoints directly instead of custom client glue

Tenant isolation

Inject tenant once, use it everywhere downstream

the-safe-default.ts

The important thing is not the syntax. It is that the tenant boundary stops being optional once the request enters the standard query path.

Dashboard delivery

Let the UI consume the typed API instead of rebuilding it

Once the backend surface is tenant-scoped and typed, the frontend can stay much thinner. Customer dashboards consume the existing API through hooks instead of inventing another analytics client inside the browser.

That does not just help the customer dashboard. The same endpoint shape can also serve support tooling or internal product surfaces without another round of hand-written typing.

Read the multi-tenant guide for the full isolation story, and the React guide if you want the hook layer details by themselves.

React hooks

A customer-facing component that stays close to the UI

dashboard-delivery.ts

The component does not need to know how tenant scoping works or how the query is built. It consumes the typed surface that the backend already owns.

Where teams usually get stuck

The questions this page should answer

What this page is really about

It is about not letting customer-facing analytics split into one-off dashboard code, one-off export code, and one-off admin code with different isolation assumptions.

Why tenant context matters so much

The safest default is to make tenant identity part of the request context and let every query read from it. That is much easier to review than trusting scattered filters.

What teams get out of this

One API surface, one scoping model, and fewer opportunities for customer-facing metrics to drift between product surfaces.

Where to go after this

Use the multi-tenant guide for the deeper isolation pattern and the dashboard or React pages for the frontend delivery side.

Next step

Start with one customer-facing metric and scope it properly

Pick a metric that reaches customers, move it behind a tenant-scoped query definition, and expose it once through the standard API path. That gives you the right foundation before the surface area multiplies.