How to migrate an Apache Cassandra table to Unified Compaction Strategy

Changing a table to Unified Compaction Strategy moves compaction decisions from a legacy per-strategy model to the UCS model introduced for Apache Cassandra 5.x. The table accepts the change through normal CQL, but the operational risk is in the SSTables that may need to be rewritten after the metadata changes.

UCS can be tuned to behave like tiered or leveled compaction by changing scaling_parameters. A table coming from SizeTieredCompactionStrategy usually starts with T4 to keep a tiered shape, while a table coming from LeveledCompactionStrategy usually starts with L10 to keep a leveled shape before later tuning.

Run the migration one table at a time during a window where extra compaction I/O is acceptable. Keep a table snapshot and the previous schema text before applying the change, because reverting the table property does not undo compaction work that has already rewritten SSTables.

Steps to migrate an Apache Cassandra table to Unified Compaction Strategy:

  1. Review the current table definition and compaction strategy.
    cqlsh> DESCRIBE TABLE sensor_app.events;
    
    CREATE TABLE sensor_app.events (
        device_id text,
        event_ts timestamp,
        reading double,
        PRIMARY KEY (device_id, event_ts)
    ) WITH CLUSTERING ORDER BY (event_ts DESC)
    ##### snipped #####
        AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}
        AND compression = {'chunk_length_in_kb': '16', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'};

    Replace sensor_app.events with the keyspace and table that are being migrated.

  2. Take a table snapshot before changing the compaction property.
    $ nodetool snapshot --table events --tag before_ucs sensor_app
    Requested creating snapshot(s) for [sensor_app] with snapshot name [before_ucs] and options {skipFlush=false}
    Snapshot directory: before_ucs

    A snapshot protects the table data on that node. It does not replace a tested restore procedure or enough disk space for both the snapshot and new compaction work.

  3. Save the current table schema with the old compaction map.
    $ cqlsh -e "DESC TABLE sensor_app.events" > sensor_app-events-before-ucs.cql

    The saved schema gives the exact previous compaction map for rollback planning.

  4. Choose the UCS scaling parameter for the source strategy.

    Use T4 when migrating from SizeTieredCompactionStrategy and preserving a tiered, write-leaning shape. Use L10 when migrating from LeveledCompactionStrategy and preserving a leveled, read-leaning shape.

  5. Alter the table to use UnifiedCompactionStrategy.
    cqlsh> ALTER TABLE sensor_app.events
       ... WITH compaction = {
       ...   'class': 'UnifiedCompactionStrategy',
       ...   'scaling_parameters': 'T4'
       ... };

    Use L10 instead of T4 when the source table was using LeveledCompactionStrategy and the migration should keep leveled behavior.

  6. Verify that the table definition now names UnifiedCompactionStrategy.
    cqlsh> DESCRIBE TABLE sensor_app.events;
    
    CREATE TABLE sensor_app.events (
        device_id text,
        event_ts timestamp,
        reading double,
        PRIMARY KEY (device_id, event_ts)
    ) WITH CLUSTERING ORDER BY (event_ts DESC)
    ##### snipped #####
        AND compaction = {'class': 'org.apache.cassandra.db.compaction.UnifiedCompactionStrategy', 'scaling_parameters': 'T4'}
        AND compression = {'chunk_length_in_kb': '16', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'};
  7. Check the table metadata directly from system_schema.tables.
    cqlsh> SELECT keyspace_name, table_name, compaction FROM system_schema.tables WHERE keyspace_name = 'sensor_app' AND table_name = 'events';
    
     keyspace_name | table_name | compaction
    ---------------+------------+-------------------------------------------------------------------------------------------------------
        sensor_app |     events | {'class': 'org.apache.cassandra.db.compaction.UnifiedCompactionStrategy', 'scaling_parameters': 'T4'}
    
    (1 rows)
  8. Watch the compaction backlog after the table property changes.
    $ nodetool compactionstats
    concurrent compactors            2
    pending tasks                    0
    compactions completed            5
    data compacted                   49329
    compactions aborted              0
    compactions reduced              0
    sstables dropped from compaction 0
    15 minute rate                   0.32/minute
    mean rate                        145.36/hour
    compaction throughput (MiB/s)    64.0

    A production table with existing SSTables can show pending compaction work after the schema change. Keep monitoring node I/O, pending tasks, and read latency until the backlog is no longer growing.