Almost everything new in 6.0 arrives switched off
There are some excellent improvements in this major release. Cassandra 6.0 coordinates transactions across partitions, takes schema and topology out of gossip, and removes real work from compaction and flushing. We have spent a lot of years explaining to customers why a schema disagreement is painful to unpick, or why a large compaction just evicted the page cache their queries depended on. It is good to see those problems addressed inside the database instead of worked around outside it.
Our friends over at AxonOps have gone into all of this in great detail, across a ten-part series written by Hayato Shimizu from two decades of running Cassandra in production. It is worth your time. This post is the quick notes: what changed, what is on by default, and what we would test before any of it goes near production.
One thing to keep in mind throughout. The line is at 6.0-alpha3 with no beta or release candidate, and Cassandra 5.0.9 remains the current GA release. This is lab work and planning, not a change ticket.
Every change in one table
| Area | What changed | Default in 6.0 |
|---|---|---|
| Accord transactions | Multi-partition BEGIN TRANSACTION with strict-serializable isolation and no cluster-wide leader (CEP-15). | Beta, accord.enabled: false |
| Cluster metadata | TCM/CMS (CEP-21) moves topology and schema out of gossip into an ordered, epoch-stamped log. | Always on in 6.0 |
| Performance | Direct I/O for compaction reads, a specialised memtable flush path, read-path allocation cuts, async GC logging. | Mostly on, direct I/O opt-in |
| Cursor compaction | Reusable descriptors replace the per-entry object graph during compaction merges. | Experimental, cursor_compaction_enabled: false |
| Zstd dictionaries | ZstdDictionaryCompressor learns repeated byte patterns from your data and reuses them across SSTable chunks. | Opt-in per table |
| Repair and guardrails | Built-in repair scheduler (CEP-37), keyspace-wide disk guardrail, driver-version guardrail, slow-query virtual table, nodetool profile. | auto_repair ships commented out |
| SAI and constraints | Indexing inside frozen collections, explicit index selection, wider LIKE filtering, CQL CHECK constraints. | Opt-in per schema |
| JDK 21 | Java 21 support with Generational ZGC selected in jvm21-server.options. | JDK 11 remains the default build |
Accord and cluster metadata
Everything else in 6.0 makes the same database faster or easier to run. These two change the contract.
Accord coordinates transactions across partitions without a leader
A transaction declares its reads, conditions and writes up front. Accord identifies the participating shards, agrees a timestamp in one round trip on the fast path, and falls back to a quorum-accepted higher timestamp under conflict. A replica that witnessed an incomplete transaction can drive recovery if the coordinator stops.
The constraints matter as much as the capability. Counter tables are unsupported. LOCAL_QUORUM, TWO and THREE are rejected. Tables need transactional_mode = 'full' or 'mixed_reads', and moving an existing table requires full repair plus Paxos repair.
TCM and CMS give metadata one ordered history
Transactional Cluster Metadata addresses schema and topology disagreement, the oldest operational pain in Cassandra. Critical metadata leaves gossip and becomes a linearized log of epochs committed by a small quorum of Cassandra nodes. No external ZooKeeper or etcd is involved. Bootstrap moves write placements before read placements in staged, acknowledged steps, so quorum intersection holds while data streams. Coordinators carry their epoch on internode messages, so a stale replica plan is caught and corrected instead of succeeding silently.
TCM is mandatory and it has an upgrade cost. Once the last node reaches 6.0, run nodetool cms initialize, then nodetool cms reconfigure to expand from one member to at least three across failure domains. Schema changes, bootstrap, decommission, moves, replacements and assassinate are prohibited until initialisation completes, so disable any automation that could attempt them.
Compaction, compression and garbage collection
| Change | The claim | The catch |
|---|---|---|
| Cursor compaction | Development benchmarks reported around 20 MB of heap allocation against more than 5 GB for the iterator path, with some mixes running three to five times faster. | Experimental. Counter tables and SSTable headers carrying dropped multi-cell columns fall back to the old path, so a cluster runs both. Alpha releases found real output differences. |
| Direct I/O | compaction_read_disk_access_mode stops large compaction scans evicting hot query pages. background_write_disk_access_mode does the same for compressed maintenance output. | You lose kernel write buffering, and direct_write_buffer_size is off-heap per concurrent writer. Memtable flushes stay buffered by design. |
| Zstd dictionaries | Tables with recurring structure such as JSON keys and repeated field names compress better, because the dictionary supplies match history across chunks. | Entirely data-dependent. High-entropy or already-compressed payloads gain little for real CPU and native-memory cost, and every retrain adds a dictionary version to keep alive. |
| Generational ZGC on JDK 21 | Short pauses, and young collections that stop repeatedly tracing the retained old set. | Cassandra's JDK 21 options disable compressed OOPs as a Jamm workaround, so the same -Xmx produces a different resident footprint. Recalculate host headroom. |
These are measurable CPU, allocation and page-cache savings. They are not a performance figure you can quote for your own cluster. Run your workload on your hardware.
Repair, guardrails and diagnostics
- Repair moves inside the database. CEP-37 adds a scheduler and replicated repair history, with bounded token-range assignments, retry state, and thresholds that hold work back when compaction or disk headroom is unsafe. It ships commented out and runs to a configured schedule. AxonOps Adaptive Repair instead regulates velocity against live 5-second telemetry and each table's
gc_grace_secondsdeadline, which is a different job. - Guardrails gain a rejection mode. A keyspace-wide disk guardrail stops writes across every replica of a keyspace instead of leaving an application partially writable. A driver-version guardrail warns or rejects clients below a declared minimum. Both need an accurate client inventory before you enable rejection.
- Diagnostic evidence improves. Slow queries land in a virtual table as well as the debug log, async profiling is reachable through
nodetool profile, and SAI state is visible insystem_views.sai_column_indexesand the related SSTable and segment views.
SAI and constraints widen your modelling options. You can index VALUES, KEYS, ENTRIES or FULL inside a frozen collection, name the index a query should use, and enforce CHECK NOT NULL, LENGTH(), scalar bounds or REGEXP in the schema. Two familiar cautions apply. Selectivity decides the cost of an index, not its existence. A constraint rejects writes from every client using that schema, including older services still in production.
What we are most interested in
TCM is the change we would have asked for first. Schema and topology disagreement has caused more awkward recovery work on customer clusters than any single performance problem, and an ordered metadata log with an epoch you can actually inspect changes what those investigations look like. The nodetool cms initialize step is a small price for it.
Cursor compaction is the other one we will be watching. If the development numbers hold up against real schemas and real SSTable history, a compaction path that allocates tens of megabytes instead of gigabytes hands CPU and GC headroom back to the nodes that need it most. It is experimental for good reason, so we would keep it in the lab for a while yet.
Accord is the change we would move slowest on. The protocol work is impressive and the CQL reads well, but transactions change how an application is designed. The rejected consistency levels, the counter-table limitation and the migration procedure all need testing against your own drivers before anyone writes code that depends on them.
What to do next
| Timeframe | Action |
|---|---|
| Now | Build the upgrade inventory: versions, topology, schema and storage profile, driver inventory, ops tooling, capacity baseline. Most upgrade surprises are already visible in it. |
| Now | Stand up 6.0-alpha3 in a lab with production-shaped data: old SSTables, tombstones, large partitions, real schema history. A freshly created test table will not exercise cursor eligibility or index cost. |
| Before GA | Rehearse the rolling upgrade including nodetool cms initialize and the automation freeze around it. Confirm monitoring, backup, restore and JMX all work against 6.0. |
| After GA, one at a time | Test Accord, Zstd dictionaries, cursor compaction, direct I/O, the repair scheduler, SAI and JDK 21 as separate changes, each with its own rollback plan. |
| Never | Combine the binary upgrade with a storage-format advance, a JDK move and a new feature. You will not be able to tell which one caused the regression. |
The full series
AxonOps have gone considerably further on every point above: configuration snippets, Jira and CEP references, contributor credits, and a test plan per feature. The full ten-part Apache Cassandra 6.0 series is on the AxonOps blog.
All 6.0 behaviour described here reflects pre-release 6.0-alpha3 and may change before GA. Check the release notes for the version you install.



