Skip to main content

Schema migration tool for Apache Cassandra

Project description

CQLTrack - A Cassandra Based Schema Versioning Tool

CI License: MIT

Schema migration tool for Apache Cassandra.

Version-controlled .cql files, distributed locking, checksum validation, multi-environment profiles, static analysis, and schema diffing — built on the DataStax Python driver.

Why cqltrack?

Most migration tools target relational databases. Cassandra is different — DDL is asynchronous, there are no transactions, and clusters span multiple datacenters. cqltrack is purpose-built for these realities:

  • Schema agreement handling — waits for all nodes to converge between DDL statements
  • Distributed locking — Lightweight Transactions (LWT) prevent concurrent migration runs across CI workers or deploy nodes
  • Partial failure tracking — if statement 3 of 5 fails, cqltrack records the failure and lets you fix and retry cleanly
  • Cassandra-native — supports NetworkTopologyStrategy, all consistency levels, LWT serial consistency for locks, and Astra DB

Features

Migrate & Rollback Versioned .cql files with -- @down rollback sections
Distributed Lock LWT-based lock with configurable TTL and auto-expiry
Checksum Validation MD5 checksums detect modified migration files
Multi-Environment YAML profiles for dev/staging/prod in one config file
Static Analysis Linter catches dangerous patterns before they hit your cluster
Schema Diff Compare schemas across keyspaces or environments
Schema Snapshot Export live schema as CQL
Partial Failure Failed migrations are tracked and retryable
Baseline Adopt cqltrack on existing databases without re-running history
CI/CD Ready pending command as a deploy gate, JSON output, exit codes
SSL/TLS Full TLS support including mutual TLS with client certificates
Astra DB Secure connect bundle support for DataStax Astra

Quick Start

# install
pip install cql-track

# start local Cassandra (optional)
docker compose up -d

# create config
cat > cqltrack.yml <<EOF
cassandra:
  contact_points: [127.0.0.1]
  port: 9042
keyspace:
  name: my_app
  replication:
    class: SimpleStrategy
    replication_factor: 1
migrations:
  directory: migrations
EOF

# initialize keyspace and tracking tables
cqltrack init

# create a migration
cqltrack new create_users_table

Edit migrations/V001__create_users_table.cql:

CREATE TABLE IF NOT EXISTS users (
    user_id    UUID,
    email      text,
    name       text,
    created_at timestamp,
    PRIMARY KEY (user_id)
);

-- @down
DROP TABLE IF EXISTS users;
# apply
cqltrack migrate

# check status
cqltrack status

Commands

cqltrack init        Create the keyspace and tracking tables
cqltrack migrate     Apply pending migrations
cqltrack rollback    Undo the most recently applied migration(s)
cqltrack status      Show applied and pending migrations
cqltrack history     Full migration history with timing and who applied
cqltrack pending     Exit code 1 if unapplied migrations exist (CI gate)
cqltrack baseline    Mark migrations as applied without executing (adoption)
cqltrack validate    Check that applied files haven't been modified
cqltrack repair      Update recorded checksums to match files on disk
cqltrack new         Scaffold a new migration file
cqltrack lint        Static analysis for dangerous CQL patterns
cqltrack snapshot    Export the live keyspace schema as CQL
cqltrack diff        Compare schemas between environments or keyspaces
cqltrack profiles    List available environment profiles

Global options:

-c, --config     Path to cqltrack.yml
--profile        Environment profile (dev, staging, prod)
-k, --keyspace   Override target keyspace
--host           Cassandra contact point(s), comma-separated
-p, --port       Cassandra native transport port
--json           Machine-readable JSON output

Configuration

cassandra:
  contact_points: [127.0.0.1]
  port: 9042
  auth:
    username: myuser
    password: mypass
  consistency: LOCAL_QUORUM       # default: LOCAL_ONE
  connect_timeout: 10
  request_timeout: 30
  ssl:
    enabled: true
    ca_certs: /path/to/ca.crt
    verify: true
  # secure_connect_bundle: /path/to/astra-bundle.zip

keyspace:
  name: my_app
  replication:
    class: NetworkTopologyStrategy
    dc1: 3
    dc2: 2

migrations:
  directory: migrations

lock:
  ttl: 600

schema:
  agreement_wait: 30

profiles:
  dev:
    keyspace:
      name: myapp_dev
  prod:
    cassandra:
      contact_points: [10.0.2.1, 10.0.2.2, 10.0.2.3]
      consistency: LOCAL_QUORUM
    keyspace:
      name: myapp_prod

Config resolution order (last wins):

  1. Built-in defaults
  2. YAML file values
  3. Profile overrides (--profile prod)
  4. Environment variables (CQLTRACK_KEYSPACE, CQLTRACK_PASSWORD, etc.)
  5. CLI flags (--keyspace, --host, --port)

Migration File Format

Files follow the naming convention V<version>__<description>.cql:

migrations/
  V001__create_users_table.cql
  V002__create_orders_table.cql
  V003__add_phone_to_users.cql

Each file has an UP section and an optional -- @down section for rollback:

-- UP: applied by `cqltrack migrate`
ALTER TABLE users ADD phone text;

-- @down
-- applied by `cqltrack rollback`
ALTER TABLE users DROP phone;

Linter

The built-in linter catches common mistakes before they hit your cluster:

$ cqltrack lint
  ERR   V005:3   [drop-no-if-exists]       DROP without IF EXISTS  not idempotent
  WARN  V008:1   [create-no-if-not-exists]  CREATE without IF NOT EXISTS
  ERR   V012:5   [column-drop]             ALTER TABLE DROP  permanently deletes data

Rules: no-rollback, empty-rollback, drop-no-if-exists, create-no-if-not-exists, column-drop, truncate, pk-alter, type-change

CI/CD

Use pending as a deploy gate:

cqltrack --profile prod pending || exit 1

Use lint in pre-commit or PR checks:

cqltrack lint

JSON output for tooling:

cqltrack --json status
cqltrack --json history
cqltrack --json pending
cqltrack --json lint
cqltrack --json diff --target-keyspace other_ks

Docker

# local Cassandra
docker compose up -d

# run cqltrack in a container
docker build -t cqltrack .
docker run --rm -v $(pwd)/migrations:/workspace/migrations \
  -v $(pwd)/cqltrack.yml:/workspace/cqltrack.yml \
  --network host cqltrack migrate

Requirements

  • Python 3.9+
  • Apache Cassandra 3.x / 4.x / 5.x, or DataStax Astra DB
  • Dependencies: cassandra-driver, click, pyyaml

Examples

See the examples/migrations/ directory for sample migration files demonstrating table creation, schema alterations, and rollback patterns.

Documentation

See USAGE.md for the complete guide — configuration reference, all commands with examples, SSL/TLS setup, Astra DB, distributed locking internals, partial failure handling, schema agreement, adoption workflow, lint rules, and troubleshooting.

Contributing

See CONTRIBUTING.md for development setup, testing, and how to submit changes.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cql_track-1.0.0.tar.gz (26.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cql_track-1.0.0-py3-none-any.whl (26.8 kB view details)

Uploaded Python 3

File details

Details for the file cql_track-1.0.0.tar.gz.

File metadata

  • Download URL: cql_track-1.0.0.tar.gz
  • Upload date:
  • Size: 26.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for cql_track-1.0.0.tar.gz
Algorithm Hash digest
SHA256 980fc1dc02f415a9847adfda01cef5950cf8e15769f23c1eff1e125d50153128
MD5 e3ad58798e6b068b5900051ce06ba8d7
BLAKE2b-256 31bfe4b194edb1b7a753e4e7f1a57365db0fc000976a83b287c05e34ea04f0df

See more details on using hashes here.

File details

Details for the file cql_track-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: cql_track-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 26.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for cql_track-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b40acda9cd6b9888b3a7c43da4094c760c710ffd7785d16eb6fd841e324f3d15
MD5 86860b98376cbb444b04b6a4a5d3bbcc
BLAKE2b-256 1200d21fb687f931fb8b6eb7df87b4e3514cefffe32e76656e07fbd9dc14d7c9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page