TTL and write timestamps

Apache Cassandra · Practical · 9 min

Sessions, caches and retention windows are handled by TTL, but expiring data has tombstone costs to plan for.

Any write can carry a time to live in seconds: INSERT ... USING TTL 86400 or UPDATE t USING TTL 3600 SET .... When it elapses, the cell expires and stops being returned. A table can set default_time_to_live so every write expires unless it specifies its own TTL.

TTL applies per cell, not per row: updating one column with a new TTL leaves the others with their old one. TTL(col) shows the remaining seconds for a cell and WRITETIME(col) its write timestamp in microseconds. A TTL of 0 means no expiry.

USING TIMESTAMP lets you set the write timestamp yourself, for example to make replays idempotent or to ensure an import doesn't overwrite newer data; normally you let the coordinator assign it.

Expired cells become tombstones and are removed by compaction after gc_grace_seconds. For time-series data where everything in a table has the same TTL and is written in time order, the TimeWindowCompactionStrategy (or UCS configured similarly) groups data by time window so whole SSTables can be dropped when they expire, which is far cheaper than compacting away individual tombstones.

Avoid mixing TTL and non-TTL data, or very different TTLs, in one time-series table, as it defeats window-based dropping.

Example

CREATE TABLE shop.sessions (
  token text PRIMARY KEY, user_id uuid, data text
) WITH default_time_to_live = 86400;          -- 1 day unless overridden

INSERT INTO shop.sessions (token, user_id, data)
VALUES ('t-abc', 5b6962dd-3f90-4c93-8f61-eabfa4a803e2, '{}') USING TTL 3600;

SELECT TTL(data), WRITETIME(data) FROM shop.sessions WHERE token = 't-abc';
--  ttl(data) | writetime(data)
--       3598 | 1760691600123456

-- sliding expiry: rewrite with a fresh TTL on each request
UPDATE shop.sessions USING TTL 3600 SET data = '{"cart": 2}' WHERE token = 't-abc';

Remember

  • USING TTL per write or default_time_to_live per table
  • TTL is per cell: updating one column doesn't refresh the others
  • TTL() and WRITETIME() inspect cells
  • Expired data becomes tombstones; TWCS drops whole expired SSTables

Watch out for

  • Refreshing the TTL on one column and expecting the whole row to live longer.

Check yourself

  1. A row was inserted with TTL 3600 on all columns. Ten minutes later you UPDATE only column b with TTL 3600. When does column a expire?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: cassandra.apache.org/doc/latest/cassandra/developing/cql/dml.html