October 21, 2025·3 min read·engineeringcassandracompactionindexesstorage

Cassandra 5.0.6 repairs index state across compaction transitions

Early-open BTI readers retain their specialized state when copied. SAI also flushes buffered segments when compaction switches its output writer.

Compaction exposes intermediate states that a completed SSTable never has. Cassandra 5.0.6, released on 21 October, fixes range queries against early-open trie-indexed files and releases SAI segment resources when output writers change. Both changes concern state that must remain correct while storage work is still in progress.

Cassandra interests me for solving distributed problems that justify its operational complexity. Local storage transitions deserve the same attention as replica placement. A cluster can have the intended replicas while an individual query fails because a reader lost the information needed to interpret an unfinished file.

An early index needs its specialized copy

The CASSANDRA-20976 patch adds a copy constructor and a sharedCopy override to PartitionIndexEarly. The constructor copies the base partition-index information and also retains the early index's cutoff and tail.

Those extra fields are the relevant distinction for this reader lifecycle. An early-open partition index cannot be represented completely by the ordinary base-class fields alone. Returning an ordinary partition-index copy loses the specialized state used by the early reader.

The new override constructs another PartitionIndexEarly. Its copy therefore preserves the subtype and the additional information. The patch is small because the missing behavior sits at the copy boundary, rather than requiring a new trie format.

The change also replaces literal length overrides with the named no-length-override constant when completing the partition index. This makes the intended file-handle state explicit. A completed index should no longer retain a limit intended for a partially readable file.

The issue identifies an assertion failure during token-range queries involving BTI SSTables. The release changelog narrows the repair to early-open BTI files. It should not be described as every indexed query requiring a new query plan or a different CQL predicate.

Error cleanup includes assertion failures

The patch broadens catches in partition-iterator creation and trie-walker initialization from selected exception classes to Throwable. Those catch blocks release already acquired reader resources before propagating the failure.

That matters for an assertion-triggered failure. Cleanup written only for runtime exceptions can omit a failure represented by another throwable category. The broader catch does not make the failed read successful. It gives resource cleanup a wider set of failure paths.

The added regression test runs verification queries while compaction creates early-open files. It reduces the early-open interval and slows compaction to make the intermediate state observable. A test that waits until compaction finishes would remove the condition under investigation.

These are fixture choices, not production tuning recommendations. Their purpose is to hold open the relevant execution interval long enough for the reader behavior to be checked.

Writer switching previously retained SAI builders

The separate CASSANDRA-20752 change adds a notification when the SSTable rewriter switches its current output writer. That notification reaches the flush observers attached to the old writer.

SAI forwards the notification to its per-column index writers. Its SSTable index writer flushes a nonempty current segment builder at that point. It does not have to wait until the full compaction transaction finishes to flush resources associated with a completed output writer.

The report explains the cost of the previous lifetime. During sharded compaction, builders for switched writers could remain until all output shards were written and committed. Retaining them unnecessarily could reduce segment sizes and contribute to memory exhaustion.

The new notification names a lifecycle event that already exists in the storage writer. Index construction can respond to that event instead of approximating it through eventual transaction completion. That is a more precise place to release writer-specific buffered state.

My preference is to align resource lifetime with the object that actually owns the work. A builder for a writer that has been switched out should not retain memory solely because other output writers remain active.

Memtable indexing keeps a different lifetime

The patch's memtable index writer implements the switch notification as a no-op. Its comment explains that the terms already reside in the memory index and remain necessary until the full flush completes. The new interface therefore does not force every implementation to discard state at the same boundary.

A regression test constructs sharded compaction with two indexes and checks that active segment builders do not accumulate beyond those needed for the indexes. It also checks the resulting shard count. This verifies both the intended resource lifetime and the presence of sharded output.

The 5.0.6 changelog records these repairs alongside other maintenance changes. For BTI readers, copying preserves the early-open state needed during compaction. For SAI writers, switching an output writer supplies an earlier opportunity to flush its buffered segment.