Intermediate Cassandra

TTL and Tombstones in Cassandra

Understand Time-To-Live for automatic data expiration and how tombstones affect read performance in Cassandra.

7 min read Tutorial

What Is TTL?

Time-To-Live (TTL) is a Cassandra feature that automatically expires data after a specified number of seconds. When the TTL elapses, the data is marked for deletion. This is invaluable for session management, temporary caches, event logs, and any data with a natural expiration.

Setting TTL on INSERT and UPDATE

You can set TTL at the row level during INSERT or at the column level during UPDATE. Each column in a row can have its own TTL.

-- Insert with 24-hour TTL (86400 seconds)
INSERT INTO sessions (session_id, user_id, token)
VALUES (uuid(), 550e8400-e29b-41d4-a716-446655440000, 'token123')
USING TTL 86400;

-- Update a column with its own TTL (1 hour)
UPDATE user_profiles USING TTL 3600
SET temp_code = 'verify-abc'
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;

-- Set default TTL for an entire table
CREATE TABLE event_logs (
  event_id UUID PRIMARY KEY,
  event_type TEXT,
  payload TEXT
) WITH default_time_to_live = 604800;  -- 7 days

Checking Remaining TTL

Use the TTL() function in a SELECT to see how many seconds remain before a column expires. The WRITETIME() function shows when the value was written.

-- Check remaining TTL on a column
SELECT session_id, token, TTL(token), WRITETIME(token)
FROM sessions
WHERE session_id = 550e8400-e29b-41d4-a716-446655440000;

-- Returns something like:
-- token | TTL(token) | WRITETIME(token)
-- abc   | 3542       | 1718467200000000

Understanding Tombstones

When data expires (via TTL) or is explicitly deleted, Cassandra does not immediately remove it from disk. Instead, it writes a special marker called a tombstone. Tombstones are necessary because Cassandra is distributed -- all replicas need to know that the data has been deleted so they do not resurrect it during repairs.

Tombstones accumulate until compaction removes them after the gc_grace_seconds period (default: 10 days). During reads, Cassandra must scan through tombstones, which can degrade performance if there are too many.

-- Explicit delete creates a tombstone
DELETE FROM users WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;

-- Setting a column to null also creates a tombstone
UPDATE users SET email = null
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;

-- Inserting null values in non-key columns creates tombstones
INSERT INTO users (user_id, name, email)
VALUES (uuid(), 'Alice', null);  -- tombstone for email

Managing Tombstones

Too many tombstones hurt read performance and can trigger the tombstone_failure_threshold warning. Here are strategies to manage them:

-- Adjust gc_grace_seconds (lower = faster cleanup)
ALTER TABLE event_logs
WITH gc_grace_seconds = 86400;  -- 1 day instead of default 10

-- Use TimeWindowCompactionStrategy for time-series data
-- Entire SSTables are dropped when all data expires
ALTER TABLE event_logs
WITH compaction = {
  'class': 'TimeWindowCompactionStrategy',
  'compaction_window_unit': 'HOURS',
  'compaction_window_size': 1
};

Best Practices

  • Avoid inserting null values -- they create unnecessary tombstones.
  • Use TTL for data with natural expiration instead of manual deletes.
  • For time-series data, use TimeWindowCompactionStrategy so expired SSTables are dropped efficiently.
  • Monitor tombstone counts using nodetool tablestats and keep gc_grace_seconds appropriate for your repair cycle.
  • Lower gc_grace_seconds only if you run repairs more frequently than the grace period.

Try this query in UnifySQL

Write, optimize, and collaborate on Cassandra queries with AI assistance.

Start Free