ClickHouse Express
Mount typed ClickHouse analytics on your Express.js server
Most backend teams already have an Express.js server. Adding ClickHouse analytics means writing route handlers, request validation, auth extraction, and documentation. @hypequery/serve provides a framework-agnostic handler that you can mount in Express with the Node adapter — validated inputs, typed responses, and OpenAPI docs included.
Framework
Express.js
Package
@hypequery/serve
Best for
Adding analytics to existing APIs
Writing Express routes for ClickHouse means raw SQL and untyped responses
The standard path is: write a raw SQL query, call @clickhouse/client, cast the response to an interface you defined manually, then return it. Every analytics route in the codebase follows this pattern — and every one is slightly different.
Every analytics route reimplements the same auth and tenant extraction boilerplate
Each route reads the Authorization header, verifies the JWT, extracts the tenantId, and injects it into the WHERE clause. This is identical logic repeated across dozens of routes, and any change to the auth flow requires touching each one.
No documentation for ClickHouse Express routes means frontend teams guess response shapes
Without a schema or OpenAPI spec, the frontend team reads the Express source code to understand what each analytics endpoint returns. When a ClickHouse column changes, there's no warning — the frontend just breaks.
How @hypequery/serve works with Express
Define analytics queries once — mount them on Express as typed endpoints
initServe() takes a context factory that runs per-request. It reads tenant and auth information from the Express request and makes it available to every query. You define analytics queries with the query() function — each one gets Zod input validation and a typed ClickHouse query builder. Then you expose the resulting `api.handler` through `createNodeHandler()` and mount that in Express.
- initServe() context factory runs per-request — reads JWT, session, or headers
- query() definitions include Zod input validation and typed ClickHouse queries
- createNodeHandler(api.handler) mounts the generated HTTP surface in Express
- OpenAPI spec generated automatically from input/output types
- Interactive Swagger UI available at /[prefix]/docs with no additional setup
Query definitions
Define analytics queries with initServe
Context is injected per-request — the auth middleware sets req.tenant, and the context factory reads it. Every query definition has access to db and tenantId without re-implementing extraction logic.
Express integration
Mount analytics routes alongside your existing Express server
createNodeHandler(api.handler) returns a Node-compatible request handler. You mount it on a path like /analytics alongside your existing routes. The analytics handler does not interfere with the rest of the Express app — it handles its own validation, error responses, and documentation.
Auth middleware runs before the analytics middleware and attaches tenant context to the request. The initServe() context factory reads that context and makes it available to all query definitions. One auth change propagates to every analytics endpoint.
The generated OpenAPI spec is available at /analytics/openapi.json. Use it to generate TypeScript client types for your frontend, validate integration tests against the schema, or import it into API gateway tooling.
Express server
Full Express server with mounted analytics routes
Existing routes are untouched. The analytics handler mounts on /analytics with auth applied upstream. OpenAPI docs are available immediately after startup.
Where teams usually get stuck
Questions teams ask
ClickHouse Express.js TypeScript
Adding analytics to Express is mostly an integration problem: validation, auth context, response contracts, and documentation. The query definitions stay separate from the framework glue.
Express analytics API ClickHouse
A production Express analytics API needs consistent auth injection, input validation, and typed response schemas. The useful pattern is one named query definition per metric, not route logic scattered across handlers.
ClickHouse REST Express
If you're serving ClickHouse data from Express, the win is not avoiding all code. It is avoiding repeated boilerplate for validation, docs, and response typing around each analytics route.
Express ClickHouse query builder
The query builder is framework-agnostic, which is the important part. Express is just one host for the handler, not the place your ClickHouse query logic has to live forever.
Further reading
Go deeper where it actually helps
ClickHouse Node.js
Node.js-specific ClickHouse patterns — the foundation for Express integration.
Open guide
ClickHouse REST API
The complete guide to serving ClickHouse queries as typed REST endpoints.
Open guide
ClickHouse OpenAPI
What the auto-generated OpenAPI spec covers and how to use it with frontend tooling.
Open guide
ClickHouse TypeScript
Schema generation and the typed query builder that powers Express analytics routes.
Open guide
Next step
Mount analytics on your Express server in under 30 minutes
Install @hypequery/serve, generate your schema with the CLI, define your first analytics query, and mount it on your Express app. OpenAPI docs are available immediately — no extra configuration.