Cassandra Garbage Collection

What Does Garbage Collector in Cassandra Do?

Cassandra garbage collection refers to the JVM’s automatic memory reclamation process that runs on every Apache Cassandra node — and the frequent stop-the-world pauses it produces when the JVM must suspend all application threads to free heap space. Because Cassandra is written in Java and runs entirely within the JVM, every node is subject to these pauses. During a stop-the-world event, all reads and writes on that node halt until the GC cycle completes.

Garbage collection in older Cassandra releases manages heap memory using a generational model: short-lived objects are allocated in the Young Generation (Eden and Survivor spaces), while objects that survive multiple collection cycles are promoted to the Old Generation. Under Cassandra’s write-heavy workloads — memtable allocations, compaction object creation, bloom filter evaluations, and replica coordination — objects are promoted rapidly. When the Old Generation fills, the JVM performs an expensive collection that, depending on the algorithm in use, may require a full stop-the-world pause lasting seconds on large heaps.

Although newer Cassandra versions introduced support for G1GC (Garbage-First Garbage Collector), which promises to reduce stop-the-world GC pauses, tuning it in production use-cases requires extensive testing and configuration cycles. Pauses exceeding 200–250 ms are considered problematic in production environments.

Pauses lasting several seconds can cause coordinator timeouts, trigger node-level alerts, and surface as p99 latency spikes visible to end users. Apache Cassandra garbage collection is one of the most operationally disruptive failure modes in production clusters — silent at the application layer until latency thresholds are breached, and requiring deep JVM expertise to diagnose.

cassandra-garbage-collection-diagram

What Causes Cassandra Garbage Collection Pauses?

GC pressure in Cassandra accumulates from several compounding sources. Understanding each is the foundation of effective cassandra tuning garbage collection.

Memtable heap pressure

Cassandra writes incoming data to an in-memory structure called the memtable before flushing it to disk as an SSTable. By default, memtables consume roughly one-third of the JVM heap — approximately 2.6 GB on an 8 GB heap. As memtables fill and flush, the resulting object allocation and promotion activity drives Young Generation collections. Large memtable configurations increase the risk of premature object promotion into the Old Generation, where collection is significantly more expensive. Moving to off-heap memtable allocation (memtable_allocation_type: offheap_objects) substantially reduces this source of cassandra garbage collection pressure.

Compaction overhead

Cassandra compaction merges SSTables and removes expired tombstones, but the process creates substantial heap objects. Each compaction thread allocates memory to store SSTable metadata and process rows’ data as well as tombstones. On a 16-core machine running one compaction thread per core, up to 1 GB of heap can be occupied by compaction work simultaneously. Leveled Compaction Strategy (LCS) generates significantly more GC garbage than Time Window Compaction Strategy (TWCS) for equivalent workloads. Reducing concurrent_compactors is a common first-line tuning step for compaction-driven GC pressure.

Row cache and bloom filters

As Cassandra uses the default SerializingCacheProvider, its row cache stores data off-heap using. Disabling row cache entirely is the standard recommendation for performance-sensitive deployments. Bloom filters are probabilistic structures Cassandra uses to avoid unnecessary SSTable reads — are also stored on-heap until very recent versions. Elevated bloom filter false-positive rates cause additional read-path object allocation, compounding heap pressure during high-read workloads.

Wide partitions and large object promotion

Partitions with compacted sizes exceeding 10 MB are a reliable indicator of GC risk. Large objects cannot be allocated in Eden and must go directly to the Old Generation, bypassing the generational collection model. Under CMS, a sustained rate of large object allocation triggers concurrent mode failure, which is a fallback to the slower Parallel stop-the-world algorithm. This produces the longest and most disruptive cassandra garbage collection pauses in the operator’s experience.

What Does Garbage Collection Do to Tombstone Columns in Cassandra?

Cassandra does not delete data from disk immediately. Instead, it writes tombstones — special markers that indicate a row or column has been deleted — which persist until gc_grace_seconds expires and compaction removes them. The term “tombstone purging” in Cassandra refers to this compaction-driven tombstone removal process: until gc_grace_seconds elapses, tombstones are retained to prevent deleted data from reappearing on nodes that were temporarily offline.

During slice queries, Cassandra must scan all rows in the queried range – including tombstones – creating DeletedColumn objects on the JVM heap for each one. In deployments with heavy delete workloads, cassandra garbage collection of tombstones can produce tens or hundreds of megabytes of heap pressure per query — an effect that grows gradually as the tombstone population accumulates and then suddenly becomes a GC incident. Cassandra logs a warning when a query scans more than tombstone_warn_threshold (default: 1,000) tombstones, and throws a TombstoneOverwhelmingException at tombstone_failure_threshold (default: 100,000). This helps operators to keep partition sizes in a healthy boundary and avoid critical GC issues. <H2>

How to Tune Cassandra Garbage Collection

Cassandra tuning garbage collection requires decisions across three dimensions: heap size, GC algorithm selection, and heap configuration parameters. Getting any one wrong compounds the others.

Heap sizing

DataStax’s auto-calculation formula is: max(min(½ RAM, 1024 MB), min(¼ RAM, 8 GB)), producing a default max heap of 8 GB on most production nodes. Always set -Xms and -Xmx to the same value to prevent resize-triggered stop-the-world pauses. For G1GC, 16–64 GB is the appropriate range. Paradoxically, heaps above 32 GB can worsen GC performance because scan cost grows proportionally with heap size.

G1GC vs. CMS

CMS (Concurrent Mark and Sweep) performs most work concurrently with the application but carries the risk of concurrent mode failure — when allocation outpaces collection, CMS falls back to a full stop-the-world Parallel GC pass. CMS is deprecated in Java 9 and removed in Java 15, but a large portion of users are running Java 8 through Java 11. G1GC divides the heap into fixed-size regions and focuses collection on the most reclaimable areas first, with a configurable pause-time target (MaxGCPauseMillis, default 200 ms). For new deployments on Java 11 or later, G1GC is the standard recommendation. Key G1GC parameters starts at: -XX:G1HeapRegionSize=16m, -XX:InitiatingHeapOccupancyPercent=45–70, -XX:MaxGCPauseMillis=200–300. These parameters are highly related to workload profiles, so it’s recommended to start from these and tune your way depending on your workload characteristics.

Off-heap memory

Setting memtable_allocation_type: offheap_objects moves memtable data out of the JVM heap into native memory, outside GC’s control. This is the single most impactful configuration change for write-heavy workloads with large text or blob values. Configure memtable_heap_space_in_mb and memtable_offheap_space_in_mb explicitly rather than relying on the automatic one-third-of-heap default. Although this setting is critical for performance, it is also one of the most common scenarios that require many cycles of tuning and might need to be revisioned as soon as the workload read:write characteristics change.

Monitoring GC health

Enable GC logging with -Xlog:gc* and analyze output with GCViewer or jstat. Key signals: any pause causing performance impact on a workload warrants investigation; concurrent mode failure in CMS logs indicates imminent GC crisis; low Survivor space utilization combined with rapid Old Generation growth signals premature promotion. In production, monitor via JMX or Prometheus with per-node GC pause dashboards. nodetool tpstats and nodetool tablehistograms provide Cassandra-level latency context alongside GC metrics.

What Is Permanent Garbage Collection in Cassandra?

Permanent garbage collection in Cassandra refers to the final removal of tombstoned data from SSTables during compaction, after gc_grace_seconds has elapsed. This is distinct from JVM garbage collection: it is Cassandra’s own data lifecycle mechanism for purging deleted rows and columns from disk. gc_grace_seconds defaults to 864,000 seconds (10 days) — long enough to ensure all cluster nodes have received and applied the deletion before the tombstone is removed. Reducing gc_grace_seconds speeds up permanent GC but increases the risk of deleted data reappearing from nodes that were offline during the tombstone propagation window.

ScyllaDB vs. Cassandra Garbage Collection

ScyllaDB is an API-compatible Apache Cassandra alternative. ScyllaDB is implemented t in C++ (not Java) on the Seastar framework. This eliminates the JVM, heap, and garbage collector.

No JVM, no GC pauses

ScyllaDB does not run in a JVM. There is no heap to size, no GC algorithm to select, no CMSInitiatingOccupancyFraction to tune, and no GCViewer output to analyze. Stop-the-world Cassandra garbage collection pauses — the defining operational burden of running Cassandra at scale — do not exist in ScyllaDB. Memory is managed explicitly using the Seastar memory allocator, designed for low-latency database workloads, without requiring periodic reclamation cycles that pause request processing.

Predictable low-latency at all percentiles

Without GC pauses, p99 and p999 latencies in ScyllaDB are bounded by hardware — disk I/O, network, and CPU — rather than by JVM collection cycles. Published benchmarks show ScyllaDB delivering 2x–5x better throughput than Cassandra with substantially lower tail latencies. A ScyllaDB cluster can be 10x smaller than an equivalent Cassandra deployment and still outperform it by 42%. The latency profile that Cassandra teams spend weeks tuning GC to approximate is ScyllaDB’s default operating mode.

No compaction-driven GC pressure

ScyllaDB’s compaction runs as a shard-local background operation using the Seastar task scheduler, which preempts compaction work to prioritize client-facing requests. Compaction does not create JVM heap objects and does not compete with reads and writes for GC headroom. ScyllaDB completes compaction 32x faster than Cassandra on equivalent hardware, and its Incremental Compaction Strategy (ICS) reduces space amplification without the write-amplification overhead of Cassandra’s Leveled Compaction Strategy.

Operational simplicity

Eliminating JVM tuning from cluster operations removes an entire category of production incident. Teams running ScyllaDB carry no ongoing engineering cost from heap sizing decisions, GC algorithm evaluation, New Generation tuning, off-heap memory configuration, or tombstone-driven GC diagnosis. ScyllaDB is API-compatible with Cassandra — existing applications, drivers, and tooling continue to work without modification.

Trending NoSQL Resources