for Cassandra, AstraDB, ScyllaDB & beyond
Purpose-built CQL migration tool. Versioned scripts, rollback, distributed locking, multi-keyspace deploys, environment profiles, and secret manager integration — across eight validated platforms including Google Bigtable, Azure CosmosDB for Cassandra, and Azure Managed Cassandra. No JVM, no XML changelogs, no compromises.
Every deploy follows a deterministic 9-step sequence. Nothing runs without validation. Nothing runs twice.
Checks all target keyspaces and the history keyspace exist in Cassandra. Exits immediately with a descriptive error if any are missing.
Writes a distributed lock row using Cassandra LWT (INSERT IF NOT EXISTS). Atomic at the cluster level — blocks concurrent deploys.
Recursively walks your migrations folder. Classifies every .cql file by prefix. Sorts versioned scripts globally by semver number.
Queries change_history to build the set of applied versions and checksums for the target keyspace. One query — no N+1.
Applies pending versioned scripts in ascending semver order. Already-applied versions are skipped automatically.
Reruns repeatable scripts whose MD5 checksum has changed since last apply. Unchanged checksums are skipped.
Always executes every deploy — no conditions, no history check. Designed for grants and permission refreshes.
Writes a SUCCESS or FAILED row to change_history for every script. Includes keyspace, checksum, tag, run_id, and execution time in ms.
Releases the lock via DELETE IF run_id = ... — a Cassandra LWT so only this process can release its own lock.
The filename is the config. No XML, no YAML changelogs — just well-named .cql files in any folder structure you choose.
Runs once, in ascending semver order. Never re-runs. The workhorse of schema evolution — CREATE TABLE, ALTER TABLE, new indexes.
Paired rollback for a versioned script. Only executes on cassachange rollback. Enables explicit, safe schema reversal — free.
Reruns on deploy when its MD5 checksum changes. Ideal for UDFs, lookup tables, and secondary views. Unchanged = skipped.
Executes on every single deploy — no conditions whatsoever. Designed for grants and permissions that must always be current.
| Script | deploy | rollback |
|---|---|---|
| V__ (versioned) | ✓ pending only | ✓ via U__ |
| U__ (undo) | — | ✓ |
| R__ (repeatable) | ✓ if changed | — |
| A__ (always) | ✓ always | — |
Scripts are discovered recursively. Organise by module, release, team — any structure. Version ordering is always global across all subdirectories.
cassachange validate.
Composable, consistent CLI. Config via YAML, environment variables, or flags. Same connection args across every command. Core migration commands plus seven complementary tools for observability, governance, and developer workflow.
The foundation. Everything cassachange needs to reliably evolve a Cassandra schema in production — versioning, safety, auditability, and recovery.
V__ scripts run once, in strict semver order, globally across all subdirectories. Applied versions are permanently recorded in change_history and never re-run.
Every versioned script can have a paired U__ undo script. Roll back the latest version or everything above a target version. ROLLED_BACK sentinels allow re-application later. Free.
INSERT IF NOT EXISTS (Paxos-backed LWT) prevents concurrent deploys at the cluster level. Lock carries a 30-minute TTL — a crashed deploy never permanently blocks future ones.
cassachange validate lints all scripts without connecting to Cassandra. Catches bad filenames, duplicate versions, orphaned undo scripts, empty files. Zero cost to run on every PR.
R__ scripts rerun when their MD5 checksum changes — ideal for UDFs and lookup tables. A__ scripts execute every deploy unconditionally — perfect for grants and permission refreshes.
When a deploy fails, repair provides a safe, fully auditable recovery path. List failures, mark them for retry, or force-release a stuck lock — without touching the database manually.
Every deploy start/end, script execution, failure, rollback, and repair is written to audit_log as an immutable append-only row. Operator, hostname, run_id, and timestamp on every event.
Run one deploy across multiple keyspaces in a single command. Each keyspace gets its own change_history rows. One lock acquired, all keyspaces migrated sequentially.
Standard Cassandra (username/password, SSL/mTLS), AstraDB (Secure Connect Bundle + token), ScyllaDB, Azure Managed Cassandra, and Amazon Keyspaces — all detected automatically from config. Enterprise adds Google Bigtable proxy and Azure CosmosDB for Cassandra. No mode flag, no manual switching.
Features that make cassachange production-grade — environment management, observability, secret security, and structured rollout controls.
Define named profiles in cassachange.yml. Each profile deep-merges over base config — connection settings, keyspaces, timeouts, notifications. Select via --profile or CASSACHANGE_PROFILE.
--dry-run-output plan.json writes a structured JSON plan — every skip (with reason) and every planned run (with checksum). Use as a CI artifact or PR comment. Implies --dry-run automatically.
Fire-and-forget notifications to Slack (Block Kit), Microsoft Teams (Adaptive Card), or any generic HTTP webhook. Failures log a WARNING — never block a deploy.
Pull credentials at runtime from HashiCorp Vault, AWS SSM, AWS Secrets Manager, or Azure Key Vault. Injected before connection opens, removed from live config — URIs never appear in logs.
Set a per-CQL-statement timeout in seconds. Raises OperationTimedOut if exceeded. Configure per-profile so dev uses the default and prod gets extra time for large schema changes.
Attach a release tag to every deploy. Tags are stored in change_history per script row. Filter status by tag, or roll back an entire release by tag name instead of hunting individual versions.
Features that smooth the day-to-day — onboarding existing clusters, introspection, and workflow tooling that keeps the team moving fast.
Point cassachange at an existing live keyspace and it generates a complete V0.0.0__baseline.cql — tables, UDTs, indexes, UDFs, UDAs. All statements use IF NOT EXISTS so the file is safe to re-run. The starting point for bringing an unmanaged cluster under version control.
Organise migrations any way you like — by module, team, release, or feature. cassachange walks the entire tree recursively, classifies every .cql file by prefix, and sorts versions globally. Folder structure never affects execution order.
Runs on Python 3.8+ with two runtime dependencies: cassandra-driver and pyyaml. No Java, no Maven, no Docker required to run migrations. Secret provider extras are optional installs only if you use them.
A production-ready 4-job pipeline ships in the package: validate (every PR) → dry-run → deploy → rollback (manual only). Rollback cannot fire on a push event. Dry-run artifact uploaded to GitHub before the real deploy runs.
Configuration priority is explicit and overridable at every layer — CLI beats env vars beats YAML beats defaults. Add CASSACHANGE_PROFILE to your CI environment and never touch a flag. Credentials stay in secrets, non-sensitive config lives in YAML.
Define keyspaces as a list in any profile. One --profile prod deploy migrates all production keyspaces in sequence — no scripts, no loops. Still overridable with --keyspace or --keyspaces on the CLI for surgical runs.
cassachange is free and open source. The enterprise edition adds secret manager integration, the immutable audit log, and a full suite of schema intelligence and observability tools.
One deploy at a time, guaranteed. Cassandra Lightweight Transactions ensure atomicity at the cluster level — no external coordination needed.
INSERT IF NOT EXISTS
TTL: 30 minutes
Uses INSERT IF NOT EXISTS — Paxos-backed atomic operation. No race conditions between concurrent CI pipelines, ever.
Lock row has a TTL baked in. A crashed deploy never permanently blocks future deploys — the lock dissolves automatically.
Release uses DELETE IF run_id = ... — another LWT. A process cannot release a lock it doesn't own, preventing accidental unlocks.
--dry-run never acquires the lock. Safe to run as many times as needed in review pipelines without blocking any real deploys.
cassachange repair --release-lock force-releases a stuck lock immediately. No need to wait for TTL or access the database directly.
When a deploy fails, repair gives you a safe, fully auditable path back. Original FAILED rows are never deleted — every state transition is preserved.
cassachange records a FAILED row in change_history. The lock is released. The cluster is in a known intermediate state.
status: FAILEDrecorded in change_history. Audit trail begins.Run repair --list to see all FAILED scripts, which keyspaces they affect, and any currently active lock rows. Zero side effects.
cassachange repair --listShows failures and lock state. No changes made.Edit the broken migration in your repo. Open a PR, get it reviewed, merge. The fix is in version control where it belongs.
Run cassachange repair. Inserts a REPAIRED sentinel row per failed script. Original FAILED rows remain — full audit chain preserved.
cassachange repair --keyspace myappInserts REPAIRED rows. No destructive changes.Run cassachange deploy. Repaired scripts are retried. On success, change_history shows the full chain: FAILED → REPAIRED → SUCCESS.
cassachange deploy --keyspace myappHistory: FAILED → REPAIRED → SUCCESSWhen a crashed deploy leaves the lock behind
All transitions are immutable rows in change_history
Apache Cassandra, AstraDB, ScyllaDB, Azure Managed Cassandra, Amazon Keyspaces — detected automatically from config. Enterprise adds Google Bigtable proxy, Azure CosmosDB for Cassandra, and Amazon Keyspaces. No mode flag, no manual switching.
Username/password. Optional SSL/mTLS.
SCB zip + application token. Protocol v4 auto-pinned.
Identical config to Cassandra. No plugin needed.
Real Cassandra nodes. mTLS auth. Natural Azure Key Vault fit.
CQL subset. LWT best-effort. No DROP TABLE / UDTs.
Via Cassandra-to-Bigtable proxy. CQL migrations — proxy translates to Bigtable API.
Cassandra-compatible API. SSL + token auth. Azure Key Vault cert support.
Connect to a live keyspace and get a scored report of schema anti-patterns, hotspot risks, TTL gaps, and index problems — before they cause incidents in production. Reads from system_schema only. No writes, no side effects.
Reads keyspace / keyspaces from your profile — same config as deploy.
Tables sorted by severity. Score per table and overall keyspace.
23 rules across 5 categories
| Rule | Severity | What it catches |
|---|---|---|
| PK001 | CRITICAL | Boolean / tinyint partition key — all data on one node |
| PK002 | WARNING | Timestamp-only partition key — time-series write hotspot |
| PK003 | WARNING | Date as first composite key component — daily write hotspot |
| PK004 | INFO | Time-series table without TTL — unbounded disk growth |
| QS001 | CRITICAL | No clustering columns + many regular columns — ALLOW FILTERING trap |
| QS002 | WARNING | 4+ clustering columns — complex slice query risk |
| QS003 | WARNING | Text / blob clustering column — unbounded sort range |
| QS004 | INFO | No clustering columns — range queries not possible |
| TH001 | CRITICAL | Session / cache / token table without TTL — unbounded growth |
| TH002 | WARNING | Append-oriented table without TTL or deletion strategy |
| TH003 | WARNING | 50+ columns — relational model transposed to Cassandra |
| TH004 | WARNING | Unbounded list / map collection — partition bloat risk |
| TH005 | CRITICAL | Counter columns mixed with regular columns — writes will fail |
| SA002 | WARNING | Integer id as partition key — sequential write hotspot |
| SA003 | WARNING | No temporal anchor and no TTL — data lifecycle unmanageable |
| SA004 | WARNING | UUID partition with no clustering — isolated row pattern |
| SA005 | INFO | Column names are CQL reserved keywords — quoting required everywhere |
| SA006 | INFO | COMPACT STORAGE — deprecated in Cassandra 4.x, removal planned |
| IR001 | WARNING | 3+ secondary indexes on one table — hidden write amplification |
| IR002 | WARNING | Secondary index on UUID / timeuuid — index as large as base table |
| IR003 | WARNING | Secondary index on boolean / tinyint — near-full cluster scan on read |
| IR004 | INFO | 8+ non-key columns with no indexes — limited access pattern flexibility |
| IR005 | INFO | SAI index present — not available on ScyllaDB or Amazon Keyspaces |
Four jobs. Rollback is manual-only by design — it can never be triggered accidentally by a push event. Dry-run artifact uploaded before real deploy runs.
Offline lint — no Cassandra connection. Catches naming errors, duplicates, orphaned undos. Zero cost to run on every PR.
Every pushGenerates migration-plan.json and uploads it as a GitHub artifact. Gives reviewers a clear view of exactly what will change before approving the deploy.
Push to mainRuns after dry-run passes. Deploys with --profile and --tag from workflow_dispatch inputs. Sends Slack notification on success or failure.
Push to mainManual trigger only — via GitHub Actions UI. Rolls back by tag or target version. Can never fire on a push event. Dry run runs first.
Manual onlyGeneral-purpose SQL migration tools are excellent for relational databases. Their Cassandra support is a community afterthought bolted on. cassachange is native.
DROP TABLE / ALTER TABLE for relational DDL. They cannot generate CQL. On paid tiers, Cassandra rollback still requires manual undo scripts — the same approach as cassachange, except cassachange is free and includes rollback-by-tag.
From CI/CD-integrated schema migrations to AI-ready vector search — hands-on Cassandra expertise for teams that want to move fast without hiring an in-house specialist.
A focused half-day or full-day session teaching your team how to use cassachange for safe, repeatable Cassandra schema migrations — including full CI/CD pipeline integration tailored to your stack.
Cassandra 5.0 brings native vector search, making it a first-class store for RAG pipelines, generative AI, and ML workloads. We design and operate the data layer your AI stack depends on.
Cassandra handles high-speed ingestion, persistent storage, and low-latency queries. Spark handles large-scale transformations, aggregations, ML, and stream processing. We wire the two together.
Embedded expertise for a sprint, a quarter, or a migration project. Schema redesign, AstraDB adoption, cassachange rollout, or a full platform audit — scoped to what you need.