Use Moose with Existing ClickHouse
Viewing:
Why Use Moose with Your Existing ClickHouse?
Moose augments your existing ClickHouse to build apps on top of your data and manage your table schemas in code.
Moose Adds to ClickHouse
Code-first schema management
Manage ClickHouse schemas in code, with Git versioning
Hot-reload dev environment
Iterate instantly without touching production
Build APIs and user-facing apps
Surface your analytics to your users with type-safe APIs
Streaming & ETL without config
Add streaming ingestion and custom workflows, no YAML
Prerequisites
Before you start
Existing ClickHouse Database
Any ClickHouse instance (Cloud, self-hosted, or playground)
Node.js 20+
Required for TypeScript development
Download →Docker Desktop
For local development environment
Download →macOS/Linux
Windows works via WSL2
Before you start
Existing ClickHouse Database
Any ClickHouse instance (Cloud, self-hosted, or playground)
Python 3.12+
Required for Python development
Download →Docker Desktop
For local development environment
Download →macOS/Linux
Windows works via WSL2
Step 1: Install Moose
Install the Moose CLI globally to your system:
bash -i <(curl -fsSL https://fiveonefour.com/install.sh) moose
Step 2: Set Up Your Project
Don't have ClickHouse?
Use the ClickHouse Playground tab to try it out!
# Generate code models from your existing ClickHouse tables
moose init my-project --from-remote <YOUR_CLICKHOUSE_CONNECTION_STRING> --language typescript
# Generate code models from your existing ClickHouse tables
moose init my-project --from-remote <YOUR_CLICKHOUSE_CONNECTION_STRING> --language python
YOUR_CLICKHOUSE_CONNECTION_STRING
is your ClickHouse connection URL in this format:
https://username:password@host:port/?database=database_name
cd my-project
npm install
cd my-project
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
You should see: Successfully generated X models from ClickHouse tables
Explore Your Generated Models
Check what Moose created from your tables in the app/main.py
file:
- main.py
Check what Moose created from your tables in the app/index.ts
file:
- index.ts
Step 3: Start Development
Start your dev server to spin up a local ClickHouse instance with all your production tables automatically reproduced from your code definitions.
moose dev
Your production ClickHouse will remain untouched.
Seed Your Local Database
You can seed your data into your local ClickHouse instance by running the following command:
moose seed --connection-string <YOUR_CLICKHOUSE_CONNECTION_STRING> --limit 100
Step 4: Adopt Moose Gradually
Now that you have your Tables defined in code, you get the same benefits as ORM data models in web apps - type safety and autocomplete when building APIs and Materialized Views on top of your analytical data.
Add APIs
Build REST APIs on top of your existing tables to expose your data to your user-facing apps. This is a great way to get started with Moose without changing any of your existing pipelines.
import { TargetSchema, materializedView } from "./myMaterializedView";
export interface QueryParams {
date: Date;
limit?: number;
}
const api = new ConsumptionApi<QueryParams, TargetSchema>("get-aggregated-data",
async ({ date, limit = 10 }: QueryParams, { client, sql }) => {
const query = sql`
SELECT * FROM ${materializedView.targetTable}
WHERE date = ${date}
LIMIT ${limit}`;
const result = await client.query.execute<TargetSchema>(query); // Type-safe query execution
return result.json();
}
);
Learn more:
Build Materialized Views
Build materialized views on top of your existing tables to improve query performance. If you have Materialized Views in your ClickHouse, you can use Moose to build new Materialized Views on top of your existing tables, or to migrate your existing Materialized Views to Moose.
// Data Model for your Materialized View- use type throughout your codebase
export interface TargetSchema {
date: Date;
count: number;
}
// Creates both the target table and the materialized view
export const materializedView = new MaterializedView<TargetSchema>({
// Raw SQL with type-safe table references
selectStatement: sql`SELECT count(*) as count, date FROM ${myTable} GROUP BY date`,
selectTables: [myTable], // Automatic dependency resolution for cascading materialized views
engine: ClickHouseEngines.MergeTree, // Can use which ever engine you want
orderByFields: ["date"],
tableName: "myAggregation",
materializedViewName: "myAggregation_MV",
});
Learn more:
Add New Data Sources
For new data sources, use Moose’s IngestPipelines to stream new data into your ClickHouse—while your legacy flows keep running. You can also use Workflows to run custom ETL pipelines if you have batch workloads.
Known Limitations
Early Access Feature
Some advanced ClickHouse features may not be fully supported yet. Join the Moose Slack and let us know if you have any issues, feedback, or requests.
Currently Unsupported Types:
Geo
types (Point, Ring, Polygon, etc.)Enum
types with empty string keys
Partial Support:
LowCardinality(T)
- Maps to base typeT
(optimization annotations available)
What we’re working on:
- Selective table import (currently imports all tables)
- Default value annotations