DEV Community

Saqib Ameen Subhan
Saqib Ameen Subhan

Posted on

A compaction strategy is a bet about your workload

Choosing a Cassandra compaction strategy is placing a bet. Each strategy optimizes one thing by deliberately sacrificing another, and the honest way to choose is to decide which failure mode you would rather operate.

I have run all three majors across 1,000+ node estates. Here is the bet each one makes.

Why compaction exists at all

Cassandra never updates in place. Writes land in a memtable, flush to immutable SSTables, and a row's fragments accumulate across many files as it is updated over time. Reads must merge every relevant fragment.

Compaction is the background process that merges SSTables, consolidating fragments and purging expired tombstones after gc_grace_seconds, so reads touch fewer files.

The metric that keeps compaction honest:

nodetool tablehistograms ks table
# Percentile  SSTables     ...
# 50%             1.00
# 99%             4.00
Enter fullscreen mode Exit fullscreen mode

SSTables per read at p99 is the number compaction exists to keep small.

STCS, SizeTiered, the write optimized default

Merges SSTables of similar size into bigger ones, repeatedly. Minimal write amplification, maximal ingest throughput.

The bet you are making: reads and disk headroom are negotiable.

  • A hot row's fragments can sit in many SSTables of different generations, so SSTables per read climbs.
  • Space amplification is the operational trap. Compacting large tiers requires holding input and output simultaneously. Plan for 50% free disk. I have watched teams treat 70% disk usage as plenty left, then be unable to run the very compaction that would reclaim space. That is a corner with no good exits.
  • Tombstones buried in giant, rarely recompacted SSTables can linger far past gc_grace_seconds.

Right when: write heavy, append mostly, reads tolerate variance. It is the default because it is the least dangerous average bet, not because it is right for you.

LCS, Leveled, paying writes to buy reads

Organizes SSTables into levels, L1, L2 and so on, each 10 times larger, guaranteeing non overlapping key ranges within a level. A read touches at most one SSTable per level, and in practice the vast majority of reads are satisfied by a single SSTable.

The bet: you will pay roughly 10x write amplification, because every row is rewritten as it migrates down levels, to make read latency tight and predictable.

  • On read heavy tables with strict p99s, it is the correct bet.
  • On write heavy tables, compaction falls behind, pending tasks pile up in nodetool compactionstats, and ironically reads degrade anyway because L0 accumulates overlapping files.
  • Easier on disk headroom than STCS, works in around 10% free, but harder on I/O and CPU, continuously.

Right when: read dominated, update in place workloads. Wrong when your disks are already busy keeping up with ingest.

TWCS, TimeWindow, the time series specialist

Groups SSTables by time window, say one per day. Within the current window, STCS as usual. Once a window closes, its SSTables compact once into one file and are never touched again.

When TTL expires a whole window, Cassandra drops the entire file, so tombstone processing effectively vanishes for aged out data. This is the single biggest tombstone fix available for time series, and the punchline of the previous post.

The bet: your data is truly time ordered and immutable once written.

  • Write out of order data or update old windows and you create cross window overlaps that can never compact away. The strategy's guarantees quietly die while everything still appears to work.
  • Rule of thumb, aim for a window size that yields 20 to 50 windows over the table's TTL.

Right when: metrics, events, telemetry, anything with TTL and append only semantics. IoT and monitoring tables at scale should almost always be TWCS.

The bet, stated plainly

Strategy You optimize You pay with Operational trap
STCS write throughput read variance needs around 50% free disk to compact
LCS read p99 10x write amplification falls behind under heavy ingest
TWCS TTL'd time series inflexibility out of order writes break it silently

Per table, not per cluster. A keyspace legitimately mixes all three. And changing the bet is an online operation:

ALTER TABLE ks.events WITH compaction =
  {'class': 'TimeWindowCompactionStrategy',
   'compaction_window_unit': 'DAYS', 'compaction_window_size': 1};
Enter fullscreen mode Exit fullscreen mode

Cassandra will re sort existing SSTables over time. On a big table, schedule the transition like the migration it is.

There is no best compaction strategy. There is only the failure mode you have chosen on purpose, versus the one that chose you.

Top comments (0)