ClickHouse Python analytics
Build ClickHouse analytics in Python once, then use it everywhere
Revenue, paying customers, and average order value start in one script and end up in jobs, notebooks, customer dashboards, and AI agents. hypequery lets you define each metric once in Python, next to your application code, so every consumer gets the same number.
Defined in
Python 3.11+
Used from
Jobs, APIs, React, agents
Tenancy
Enforced on every query
The same metric, five implementations
Revenue lives in a cron job, a notebook, an API handler, and a dashboard query. Each copy filters completed orders slightly differently, and the numbers stop matching.
Joins and ratios get rebuilt by hand
Revenue by customer plan needs a join. Average order value needs a guarded division. Every new report rewrites both, and every rewrite is a chance to get them wrong.
Customer-facing numbers need hard boundaries
Once analytics reach customers, a missing tenant filter is a data leak. A convention in SQL strings is not enough when several services query the same tables.
Define
Write the metrics as Python, next to your app
A dataset maps a ClickHouse table to named dimensions and measures. Filtered measures, derived ratios, and to-one joins are part of the definition, so callers ask for average_order_value instead of rebuilding it.
- Sums, counts, exact distinct counts, percentiles, and filtered measures
- Derived measures with null-safe division, like average order value
belongs_torelationships, so callers can group bycustomer.plan- Tenant and time keys declared once and enforced on every query
Dataset
Orders, with the metrics your product reports
The completed filter is defined once and shared by every measure that needs it.
Use
One client for jobs, notebooks, dashboards, and agents
Query measures by name with a time grain, and hypequery plans parameterized ClickHouse SQL with the join and the tenant predicate on both tables. Serve the same datasets over HTTP when a dashboard or agent needs them.
Results are cached under opaque, tenant-keyed entries, so a dashboard reloading the same chart does not rescan ClickHouse, and two customers never share an entry.
The HTTP endpoint authenticates every request and takes the tenant from the caller, not the request body. include_related lets callers group by customer.plan over HTTP, and client_profile plus the client-contract route are what generated React hooks and the MCP bridge read. See React and MCP clients for exporting the contract.
Consumers
A monthly report and an authenticated API, from one definition
ClickHouseConnection.from_env() reads CLICKHOUSE_URL or the CLICKHOUSE_* variables.
Where teams usually get stuck
Questions teams ask
ClickHouse analytics with Python
Use a driver like clickhouse-connect for ad hoc SQL. Use hypequery datasets for the metrics other code depends on, so there is one definition to review and change.
Product analytics in a Python backend
Serve tenant-scoped metrics from FastAPI, Django, Flask, or any ASGI or WSGI app, and render them with typed React hooks.
Not a BI tool
There is no separate server to run or YAML to maintain. Definitions are Python in your repository, reviewed and tested like the rest of your code.
What is TypeScript-only for now
Window measures (trailing, to-date, cumulative) and period comparisons are TypeScript only. The Python SDK is in beta; see feature status for the full list.
Further reading
Go deeper where it actually helps
Measures
Aggregations, filtered measures, and derived formulas.
Open guide
Relationships
Group and filter by fields on related datasets.
Open guide
Caching
Tenant-safe result caching with opaque keys.
Open guide
Serving
Authenticated HTTP endpoints from any ASGI or WSGI app.
Open guide
React and MCP clients
Export the client contract for typed React hooks and the MCP bridge.
Open guide
FastAPI and React analytics
Typed React hooks on the endpoints your Python app serves.
Open guide
Python feature status
What ships in the beta, and what is TypeScript-only for now.
Open guide
Next step
Move one shared metric into a dataset
Pick the number your team argues about most, define it once, and point one job and one dashboard at it.
Open source, and it runs in your own backend. Want it hosted?