Retention and log compaction

Apache Kafka · Practical · 12 min

Retention decides storage cost and how far back consumers can replay; compaction turns a topic into a changelog of current state.

Each partition is stored as a series of segment files. Old data is removed a whole segment at a time according to the topic's cleanup.policy.

With cleanup.policy=delete (the default), segments are deleted when they are older than retention.ms (7 days by default) or when the partition exceeds retention.bytes (unlimited by default). Set retention.ms=-1 to keep data forever. Because only closed segments are deleted, data can live somewhat longer than the retention setting.

With cleanup.policy=compact, Kafka keeps at least the latest record for each key and removes older ones in the background. The topic becomes a changelog: replaying it from the start yields the current state of every key. Uses: user profiles, configuration, Kafka Streams state, CDC tables.

  • A record with a key and a null value is a tombstone: it marks the key as deleted, and is itself removed after delete.retention.ms (1 day by default).
  • Compaction never touches the active segment, and offsets never change; compacted topics simply have gaps.
  • compact,delete combines both: latest value per key, but nothing older than the retention time.

Retention is set per topic with kafka-configs.sh --alter --entity-type topics, and changes apply without restarts.

Example

# keep 3 days of clickstream data
kafka-configs.sh --bootstrap-server localhost:9092 --alter \
  --entity-type topics --entity-name clicks --add-config retention.ms=259200000

# a compacted topic holding the latest profile per user
kafka-topics.sh --bootstrap-server localhost:9092 --create --topic user-profiles \
  --partitions 6 --replication-factor 3 --config cleanup.policy=compact

# records over time (key:value)       after compaction
#   u1:{"name":"Ann"}                   u2:{"name":"Bob"}
#   u2:{"name":"Bob"}                   u1:{"name":"Ann K."}
#   u1:{"name":"Ann K."}                u3:null  (tombstone, removed later)
#   u3:{"name":"Cy"}
#   u3:null

Remember

  • delete policy: drop segments older than retention.ms or beyond retention.bytes
  • compact policy: keep at least the latest value per key
  • A null value is a tombstone that deletes a key
  • Cleanup works on closed segments; offsets never change

Watch out for

  • Expecting a compacted topic to contain only one record per key at all times; recent duplicates remain until compaction runs.

Check yourself

  1. How do you delete key 'u3' from a compacted topic?

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

Official docs: kafka.apache.org/43/design/design/#log-compaction