apps/api/migrations/clickhouse-migrations/README.md
This directory contains SQL migration files for ClickHouse database schema management.
Migrations are managed using the clickhouse-migrations npm package, which provides:
migrations table in ClickHouseMigration files must follow this naming pattern:
<number>_<description>.sql
Examples:
1_initial_schema.sql2_add_user_preferences_table.sql3_add_index_on_workflow_runs.sqlThe number prefix determines execution order. Migrations are applied in ascending numerical order.
Use Idempotent SQL: Always use conditional statements to ensure migrations can be safely re-run:
CREATE TABLE IF NOT EXISTS my_table (...);
ALTER TABLE my_table ADD COLUMN IF NOT EXISTS new_column String;
CREATE INDEX IF NOT EXISTS idx_name ON my_table (column);
One Logical Change Per File: Keep migrations focused on a single schema change for easier rollback and debugging.
Include Comments: Document the purpose and context of each migration:
-- Add user timezone preference
-- Ticket: NV-1234
ALTER TABLE users ADD COLUMN IF NOT EXISTS timezone String DEFAULT 'UTC';
Multiple Statements: Separate statements with semicolons (;):
CREATE TABLE IF NOT EXISTS table1 (...);
CREATE TABLE IF NOT EXISTS table2 (...);
ClickHouse Settings: Include query-level settings as needed:
SET allow_experimental_json_type = 1;
CREATE TABLE IF NOT EXISTS events (data JSON) ENGINE = MergeTree ...;
Ensure ClickHouse is running locally (via Docker Compose):
cd /path/to/novu
docker-compose -f docker/local/docker-compose.yml up -d clickhouse
cd apps/api
pnpm run clickhouse:migrate
The local script uses hardcoded values:
http://localhost:8123defaultnovu-localThe script will:
migrations tracking table if it doesn't existFor production and staging environments, use:
pnpm run clickhouse:migrate:prod
This script relies on native clickhouse-migrations environment variables:
CH_MIGRATIONS_HOST - ClickHouse server URL (e.g., http://clickhouse.example.com:8123)CH_MIGRATIONS_USER - Database usernameCH_MIGRATIONS_PASSWORD - Database passwordCH_MIGRATIONS_DB - Target database nameCH_MIGRATIONS_HOME - Migrations directory (optional, defaults to ./migrations/clickhouse-migrations)These should be set in your deployment environment (GitHub Actions secrets, Kubernetes secrets, etc.).
Migrations run automatically in CI/CD before deployments using pnpm run clickhouse:migrate:prod:
-- Add step execution metrics
-- This migration adds performance tracking columns to step_runs table
ALTER TABLE IF EXISTS step_runs
ADD COLUMN IF NOT EXISTS execution_time_ms UInt32 DEFAULT 0,
ADD COLUMN IF NOT EXISTS retry_count UInt8 DEFAULT 0;
-- Add index for performance queries
CREATE INDEX IF NOT EXISTS idx_step_runs_execution_time
ON step_runs (execution_time_ms)
TYPE minmax GRANULARITY 4;
If a migration fails during deployment:
pnpm run clickhouse:migrateTo reset your local ClickHouse and re-run all migrations:
# Drop the database
docker exec -it clickhouse_main clickhouse-client --query "DROP DATABASE IF EXISTS \`novu-local\`"
# Recreate and run migrations
pnpm run clickhouse:migrate
To see which migrations have been applied:
docker exec -it clickhouse_main clickhouse-client --query "SELECT * FROM \`novu-local\`.migrations ORDER BY version"
Current tables managed by migrations:
step_runs - Individual step executions within workflowstraces - Event traces for debugging and monitoringrequests - HTTP request logsworkflow_runs - Complete workflow execution instancesFor detailed schema definitions, see the TypeScript schema files in:
libs/application-generic/src/services/analytic-logs/