Why Cassandra Time-Series Tables Need TimeWindowCompactionStrategy
Append-only time-series data in Cassandra suffers under the default SizeTieredCompactionStrategy. TWCS buckets writes into fixed time windows, cutting rewrite overhead and making TTL cleanup cheap—if your workload fits its constraints.
11 Nov 2025, 09:18 UTC

The problem: default compaction rewrites history
Apache Cassandra stores writes in immutable SSTables (sorted string tables) on disk. A background process called compaction periodically merges these files to discard overwritten values and tombstones (deletion markers). The default strategy, SizeTieredCompactionStrategy (STCS), groups SSTables by similar size and merges them regardless of age. On an append-only time-series table—say, millions of sensor readings per minute—that means the compaction engine keeps rewriting last week’s data alongside today’s readings. The result is write amplification: your cluster performs far more disk I/O than the incoming write rate requires, and disk headroom disappears because old SSTables are repeatedly merged rather than dropped.
The useful takeaway: if your table is append-only and you expire data with TTL, TimeWindowCompactionStrategy (TWCS) usually lowers total I/O and lets entire expired windows vanish without row-level tombstone cleanup.
How TWCS buckets data by time
TWCS assigns each SSTable to a fixed time window based on the timestamps of the rows it contains. You configure the window with compaction_window_size and compaction_window_unit. Compaction then only merges SSTables that fall inside the same window. Once every row in a window has passed its TTL, Cassandra can drop the whole set of SSTables for that window instead of compacting millions of individual tombstones.
This behavior is production-supported in Apache Cassandra 3.x and 4.x, alongside STCS and LeveledCompactionStrategy.
Worked example: a sensor_readings table
Suppose you collect temperature readings every few seconds and keep them for 7 days. Create the table with TWCS in cqlsh (run on any client node with CREATE permissions on the keyspace):
CREATE TABLE sensor_readings (
sensor_id uuid,
reading_ts timestamp,
value double,
PRIMARY KEY ((sensor_id), reading_ts)
) WITH compaction = {
'class': 'TimeWindowCompactionStrategy',
'compaction_window_size': '1',
'compaction_window_unit': 'DAYS'
}
AND default_time_to_live = 604800;
After creating the table, verify the strategy by running DESCRIBE TABLE sensor_readings; in cqlsh. Confirm the output lists TimeWindowCompactionStrategy and the window size you set.
During a sustained write load, run nodetool compactionstats on a Cassandra node (requires JMX access, typically as the service account or an operator with nodetool permissions). You should see pending compactions bounded to a single day’s SSTables rather than a major compaction spanning the entire table history.
To validate TTL cleanup, insert a batch of rows with a short TTL—for example, 300 seconds—and wait for expiration. With TWCS, the expired window should be discarded as whole SSTables. With STCS, you would instead see individual tombstones accumulate until a later compaction merges them.
The trade-offs you must accept
TWCS is not a universal replacement for STCS.
- Out-of-order writes scatter data. If your application backfills historical timestamps or writes late-arriving events, those SSTables land in older windows. Cassandra will not compact them with newer data, so disk usage grows and read latency suffers because reads must check many windows.
- Deletes and updates in old windows linger. TWCS does not compact across window boundaries. An explicit
DELETEor anUPDATEthat creates a tombstone in a window from three days ago will not be reclaimed until that window fully expires. If your workload mutates historical rows, STCS or LCS may reclaim space sooner. - Changing strategy on a live table is disruptive. Executing
ALTER TABLE ... WITH compaction = {'class': 'TimeWindowCompactionStrategy', ...}on a populated table triggers a major compaction. Disk and I/O usage will spike temporarily. Reverting to STCS later triggers another major compaction, so schedule the change during a maintenance window and ensure enough free disk space for the rewrite.
Actionable closing
Choose TWCS when your table is append-only, time-ordered, and governed by TTL or window-based retention. Match compaction_window_size to your retention granularity—daily windows for a 7-day sensor log, hourly windows for a 3-day cache. Before switching a production table, confirm the workload is truly append-only, provision extra disk for the initial major compaction, and verify afterward with DESCRIBE TABLE and nodetool compactionstats. If you need frequent updates or deletes on old data, stay with STCS or evaluate LeveledCompactionStrategy instead.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.