Why it matters

Storage cost in HBase grows with retention. A table that keeps every version of every cell forever accumulates linearly with write rate; a table with tight TTL bounds storage regardless of write rate. Getting these right is worth thousands of dollars per month for large deployments.

Query correctness also depends on version semantics. Applications assuming only-latest-value can be surprised by ancient values reappearing after a compaction if MAX_VERSIONS is higher than expected.

Advertisement

The architecture

TTL is set per column family. When enabled, cells are considered expired if their timestamp is older than the TTL relative to current time. Expired cells still exist physically until compaction removes them, but they are invisible to reads (the scanner filters them out).

MAX_VERSIONS is also per column family. When enabled, only the most recent N versions of each cell are retained. Older versions are considered obsolete and are removed during major compaction.

TTL and versions — automatic data lifecycleTTLcell expires after N secondsMAX_VERSIONSkeep N versions per cellEnforced during major compaction: expired/superseded cells dropped from output HFile
TTL bounds age; MAX_VERSIONS bounds count. Both enforced at major compaction.
Advertisement

How it works end to end

Both settings are enforced at compaction time, not at write time. Writes always succeed; the expired or obsolete data is dropped when compaction produces new HFiles. This means storage does not shrink immediately when you tighten TTL — you need to trigger compaction for the physical cleanup.

Reads honor the settings immediately. A get or scan filters out expired cells and returns only the N most recent versions per cell. So even before compaction runs, reads see the correct data.

Combining TTL and MAX_VERSIONS is common. A logging table might set TTL to 90 days and MAX_VERSIONS to 1 (keep only the latest for 90 days). A user profile table might set TTL to 5 years and MAX_VERSIONS to 3 (keep last 3 versions for 5 years).