Skip to content

AxonOps — AI-Native Control Plane for Open Source Data Platforms

Cassandra Data Compaction

Compaction is the process of merging SSTables to reduce read amplification, reclaim space from tombstones, and maintain manageable file counts. Selecting an appropriate strategy and configuration is critical for cluster performance.

Cassandra 5.0+ Recommendation

For new deployments on Cassandra 5.0+, Unified Compaction Strategy (UCS) is the recommended default. UCS provides a single, configurable strategy that can emulate STCS, LCS, or hybrid behaviors through its scaling_parameters option. Existing clusters can continue using their current strategies or migrate to UCS via ALTER TABLE, though migration should be validated against workload characteristics and monitored for operational impact.


As described in the Write Path, Cassandra writes first go to the commit log and memtable. When a memtable reaches its threshold, it flushes to disk as an immutable SSTable. This append-only design enables fast writes but creates a side effect: SSTables accumulate continuously.

SSTable accumulation from repeated memtable flushesSSTable accumulation from repeated memtable flushesDisk (SSTables accumulate over time)SSTable 1(Day 1)SSTable 2(Day 2)SSTable 3(Day 3)...SSTable N(Day N)WritesMemtablewriteflushflushflushflush

Each flush creates a new SSTable containing:

  • Data from the memtable at flush time
  • Potentially overlapping partition keys with existing SSTables
  • Updated values for previously written rows
  • Tombstones for deleted data

Without intervention, a table receiving continuous writes accumulates hundreds or thousands of SSTables. This creates problems for both reads and disk management.


Without compaction, SSTable accumulation degrades read performance:

Read checking every SSTable when compaction does not runRead checking every SSTable when compaction does not runAfter 100 Days: 100 SSTablesSSTable 1SSTable 2SSTable 3...SSTable 100Read 'user123'Potentially 100disk seekscheckcheckcheckcheck

Each read must check bloom filters across all SSTables. Even with bloom filter optimization, false positives accumulate—potentially requiring disk seeks to dozens of SSTables for a single partition read.


Merging four SSTables into one compacted SSTableMerging four SSTables into one compacted SSTableBefore CompactionCompaction ProcessAfter CompactionSSTable 1user123→Auser789→DSSTable 2user123→Buser456→YSSTable 3user456→XSSTable 4user123→C(deleted)1. Merge-sort all SSTables2. Keep newest timestamp per cell3. Apply tombstones4. Discard expired tombstonesNew SSTableuser123→C (newest)user456→X (merged)user789→D(deletion applied)
BenefitDescription
Reduces read amplificationFewer SSTables to check per read
Reclaims spaceRemoves tombstones after gc_grace_seconds
Removes obsolete dataDiscards old versions of updated cells
Improves compressionLarger, consolidated data compresses better
Updates statisticsRefreshes min/max values, partition sizes

Every compaction strategy involves trade-offs between three types of amplification.

How many times data is written to disk over its lifetime.

Write Amplification=Total Bytes Written to DiskBytes Received from Client\text{Write Amplification} = \frac{\text{Total Bytes Written to Disk}}{\text{Bytes Received from Client}}

Example:

  • Client writes 1GB of data
  • Data is written once to commit log
  • Data is written once to SSTable (memtable flush)
  • Data is rewritten 3× during compaction
  • Write amplification = 1+1+31=5×\frac{1 + 1 + 3}{1} = 5\times

Impact:

  • Higher write amplification increases disk I/O
  • SSD lifetime is measured in total bytes written
  • Write amplification of 10× means SSD wears 10× faster

How many SSTables must be checked per read.

Read Amplification=Number of SSTables Touched per Read\text{Read Amplification} = \text{Number of SSTables Touched per Read}

CaseRead Amplification
Ideal (fully consolidated)11
Worst (no compaction)NN (one per flush)

Impact:

  • Higher read amplification increases disk seeks and latency
  • With HDDs: Each SSTable check ≈ 10ms seek time
  • With SSDs: Each SSTable check ≈ 0.1ms
  • Significantly affects P99 latency

How much extra disk space is needed beyond raw data size.

Space Amplification=Disk Space UsedActual Data Size\text{Space Amplification} = \frac{\text{Disk Space Used}}{\text{Actual Data Size}}

Example:

  • Raw data: 100GB
  • Tombstones pending cleanup: 10GB
  • Old SSTable versions during compaction: 100GB (temporary)
  • Space amplification = 210GB100GB=2.1×\frac{210\text{GB}}{100\text{GB}} = 2.1\times

Impact:

  • Determines required disk headroom
  • Some strategies need 2× space temporarily during compaction
  • Running out of disk during compaction causes failures

StrategyWrite AmpRead AmpSpace AmpBest For
STCSLowHighMediumWrite-heavy workloads
LCSHighLowLowRead-heavy workloads
TWCSLowLowLowTime-series with TTL
UCSVariesVariesLowAdaptive (Cassandra 5.0+)

Compaction strategy selection by Cassandra version and workloadCompaction strategy selection by Cassandra version and workloadThis syntax is deprecated, you must add <<#E8F5E9>> at the end of the line, after the ';'UCS (recommended)Configure scaling_parametersbased on workloadYESCassandra 5.0+?NOTWCSYESIs the data time-series with TTL?NOIs the workload >70% reads?YESNOAre SSDs available?YESNOLCSSTCSSTCS
WorkloadCassandra 5.0+Pre-5.0Rationale
Write-heavy (>90% writes)UCS (T8)STCSLow write amplification
Read-heavy (>70% reads)UCS (L10)LCSLow read amplification
Time-series with TTLTWCS or UCSTWCSEfficient TTL expiration
Mixed workloadUCS (T4)STCSBalanced trade-offs
Frequently updated dataUCS (L4)LCSConsolidates versions quickly
Append-only logsUCS (T4) or TWCSSTCS or TWCSMinimal rewrites

MetricWarningCriticalAction
Pending compactions>50>200Increase throughput
SSTable count (STCS)>20>50Check compaction progress
L0 SSTable count (LCS)>8>32Throttle writes or switch strategy
Compaction throughput<50% configured<25% configuredCheck disk I/O
Disk space free<30%<20%Add storage or run compaction
Terminal window
# Current compaction activity
nodetool compactionstats
# Per-table SSTable count and sizes
nodetool tablestats keyspace.table
# Compaction history
nodetool compactionhistory
# SSTable count per level (LCS)
nodetool tablestats keyspace.table | grep "SSTables in each level"
# Pending compactions
org.apache.cassandra.metrics:type=Compaction,name=PendingTasks
# Compaction throughput (bytes/second)
org.apache.cassandra.metrics:type=Compaction,name=BytesCompacted
# Per-table metrics
org.apache.cassandra.metrics:type=Table,keyspace=*,scope=*,name=LiveSSTableCount
org.apache.cassandra.metrics:type=Table,keyspace=*,scope=*,name=PendingCompactions

  1. Never disable auto-compaction unless there is a specific operational reason
  2. Avoid major compaction during normal production operations
  3. Monitor pending tasks - sustained growth indicates a problem
  4. Maintain 30%+ free disk space for compaction headroom
  5. Run repair regularly to prevent zombie data after tombstone removal
cassandra.yaml
# Maximum compaction throughput per node (MB/s)
# Higher = faster compaction, more disk I/O competition
# 0 = unlimited
compaction_throughput_mb_per_sec: 64
# Number of concurrent compaction threads
# Default: min(4, number_of_disks)
concurrent_compactors: 4
Terminal window
# Adjust at runtime
nodetool setcompactionthroughput 128
nodetool setconcurrentcompactors 4