Use this skill when creating, running, or managing database migrations for PostgreSQL or ClickHouse. This includes creating new migrations, running migrations, checking migration status, rollback operations, seeding data, or troubleshooting migration issues.
Expert guidance for database migrations with PostgreSQL, ClickHouse, and seeding operations.
Location: cmd/migrate/main.go
Key Features:
-db postgres|clickhouse|all)# Run all database migrations
make migrate-up
# Rollback one migration
make migrate-down
# Check migration status
make migrate-status
# Create new migration
make create-migration DB=postgres NAME=add_users_table
make create-migration DB=clickhouse NAME=add_metrics_table
# Reset all databases (WARNING: destroys data)
make migrate-reset
# Seed with development data
make seed-dev
# Database shell access
make shell-db # PostgreSQL
make shell-redis # Redis CLI
make shell-clickhouse # ClickHouse client
# Run migrations for specific databases
go run cmd/migrate/main.go -db postgres up
go run cmd/migrate/main.go -db clickhouse up
go run cmd/migrate/main.go up # All databases
# Check detailed migration status
go run cmd/migrate/main.go -db postgres status
go run cmd/migrate/main.go -db clickhouse status
go run cmd/migrate/main.go status # Both with health check
# Rollback migrations (requires confirmation)
go run cmd/migrate/main.go -db postgres down
go run cmd/migrate/main.go -db clickhouse down
go run cmd/migrate/main.go down # Both databases
# Create new migrations
go run cmd/migrate/main.go -db postgres -name create_users_table create
go run cmd/migrate/main.go -db clickhouse -name create_metrics_table create
# Destructive operations (requires 'yes' confirmation)
go run cmd/migrate/main.go -db postgres drop
go run cmd/migrate/main.go -db clickhouse drop
# Granular step control
go run cmd/migrate/main.go -db postgres -steps 2 up # Run 2 forward
go run cmd/migrate/main.go -db postgres -steps -1 down # Rollback 1
# Force operations (DANGEROUS - use only when dirty)
go run cmd/migrate/main.go -db postgres -version 0 force
go run cmd/migrate/main.go -db clickhouse -version 5 force
# Information and debugging
go run cmd/migrate/main.go info
go run cmd/migrate/main.go -dry-run up # Preview without executing
Primary tables in migrations/clickhouse/:
TTL: All tables use 365-day retention
Reference: Check migrations/clickhouse/*.up.sql for exact schema, TTL configuration, and indexes
-- migrations/000042_add_feature_table.up.sql
-- +migrate Up
CREATE TABLE IF NOT EXISTS feature_table (
id VARCHAR(26) PRIMARY KEY,
organization_id VARCHAR(26) NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
status VARCHAR(50) NOT NULL DEFAULT 'active',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_feature_table_organization_id ON feature_table(organization_id);
CREATE INDEX idx_feature_table_status ON feature_table(status);
-- +migrate Down
DROP INDEX IF EXISTS idx_feature_table_status;
DROP INDEX IF EXISTS idx_feature_table_organization_id;
DROP TABLE IF EXISTS feature_table;
-- migrations/clickhouse/000005_add_metrics_table.up.sql
-- +migrate Up
CREATE TABLE IF NOT EXISTS metrics (
id String,
organization_id String,
project_id String,
metric_name String,
metric_value Float64,
timestamp DateTime64(3),
metadata String, -- JSON stored as String
created_at DateTime64(3) DEFAULT now64(3)
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(timestamp)
ORDER BY (organization_id, project_id, timestamp)
TTL toDateTime(timestamp) + INTERVAL 365 DAY
SETTINGS index_granularity = 8192;
-- +migrate Down
DROP TABLE IF EXISTS metrics;
CREATE TABLE spans (
-- Core fields
id String,
trace_id String,
-- OTEL-native: All attributes in one field with namespace prefixes
attributes String, -- {"brokle.model": "gpt-4", "brokle.tokens": 150}
-- OTEL metadata
metadata String, -- {"resourceAttributes": {...}, "instrumentationScope": {...}}
-- Timestamps
start_time DateTime64(3),
end_time Nullable(DateTime64(3)),
-- ZSTD compression for large fields
input Nullable(String) CODEC(ZSTD),
output Nullable(String) CODEC(ZSTD),
-- Application version for A/B testing
version Nullable(String),
created_at DateTime64(3) DEFAULT now64(3)
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(start_time)
ORDER BY (trace_id, start_time)
TTL start_time + INTERVAL 90 DAY
SETTINGS index_granularity = 8192;
PARTITION BY toYYYYMM(timestamp) for time-seriesORDER BY for query optimizationTTL toDateTime(timestamp) + INTERVAL 365 DAY for automatic retentionCODEC(ZSTD) for large text fields (78% cost reduction)index_granularity = 8192 for optimal performanceReplacingMergeTree(event_ts, is_deleted) for soft-delete supportString (not UUID)DateTime64(3) for millisecond precisionString (store as JSON string, query with JSON functions)Nullable(Type)seeds/)# seeds/dev.yaml