ClickHouse Node.js
Use ClickHouse from Node.js without hand-maintained query types
This page is narrower than the JavaScript page. It is about the backend reality: scripts, workers, Express servers, and the point where a query needs to become a reusable API instead of another helper buried in a service file.
Runtime
Node.js and Bun
Frameworks
Express, Next.js, custom Node servers
Type source
Generated from schema
Node services accumulate query helpers fast
A server codebase rarely has just one query caller. Jobs, workers, route handlers, and admin tasks all want the same data, and each one tends to grow its own helper if there is no shared path.
The HTTP layer keeps getting rebuilt
Once a query needs an endpoint, teams start writing validation, auth handling, error shaping, and docs around it. That is a lot of repeated backend work for what should still be one analytics query.
Type mismatches hide inside server code
Node developers often spot the runtime mismatch later because the wrong shape is hidden inside service code and only surfaces after it has already passed through several layers.
Setup
Start with a typed backend query layer, not another helper module
Generate the schema once, initialize the builder in your backend, and make that the standard way Node code reaches ClickHouse. That gives scripts, workers, and services the same typed starting point.
- Works well in Node.js services, scripts, and Bun runtimes
- Schema types generated from your live ClickHouse instance
- Correct ClickHouse-to-Node.js type mappings — no guessing
- Composable query builder with support for typed filters, joins, CTEs, and raw SQL when needed
- Optional HTTP serving layer via @hypequery/serve handlers
Setup
A backend entry point you can reuse across services and jobs
The point of this setup is consistency. Once the builder exists in one standard place, the rest of the Node codebase stops reinventing how it talks to ClickHouse.
With Express
Promote a query into an endpoint without burying logic in the route
When Node code needs to expose analytics over HTTP, keep the query definition separate from the web framework and mount the handler around it. That keeps the route thin and the analytics logic reusable.
That separation is what makes the Node page distinct from the framework pages. The query can still run directly inside a job or script, and only becomes an HTTP concern when you actually need a server surface.
If your app is specifically App Router-first, use the Next.js page. This page is for the general backend case where Express-style or standalone Node runtimes are still the center of gravity.
Express integration
A thin Express mount around a shared analytics definition
The useful part is not the middleware line by itself. It is that the route is no longer where the analytics logic lives.
Where teams usually get stuck
The questions this page should answer
What this page is really for
It is for backend teams whose main concern is service code, jobs, and server routes, not client hooks or App Router rendering.
Where Node teams usually feel pain
Usually when the same query appears in a worker, a route, and a report generator and every copy evolves separately.
Why the server layer matters
Backend teams end up paying for every decision twice if query logic and route logic are fused together. This page is about keeping them separate.
Where to branch next
Use the Next.js page for App Router specifics and the REST page if the endpoint layer itself is your main concern.
Further reading
Go deeper where it actually helps
ClickHouse JavaScript
The broader JavaScript and TypeScript guide — the same patterns in a framework-agnostic context.
Open guide
ClickHouse Next.js
Integrating ClickHouse into Next.js App Router — server components and API routes.
Open guide
ClickHouse REST API
Full guide to serving typed ClickHouse queries as HTTP endpoints with @hypequery/serve.
Open guide
ClickHouse TypeScript
The full TypeScript workflow — schema types, typed queries, HTTP APIs, and React hooks.
Open guide
Next step
Replace one backend query path end to end
Pick one script, worker, or route that currently owns its own ClickHouse query code, move it onto the shared builder, and then decide whether it also deserves a served API surface.