Skip to main content

Log Compaction, Retention & Tiered Storage

Level 6: Level 6: Asynchronous & Event-Driven Systemsmedium30 mincompactionretentiontiered-storage

Delete-retention makes a replayable stream, compaction makes a rebuildable table/changelog with tombstones, tiered storage makes long retention cheap, and dedup must cover the replay window.

Retention decides what a topic is

The same append-only log behaves as a replayable event stream or as a queryable table depending entirely on how you retain it, and getting this wrong is how teams either blow up storage cost or lose the ability to rebuild state.

Two fundamentally different retention policies

Delete retention (time or size): keep records for a window, then delete whole old segments. retention.ms=604800000 keeps 7 days; retention.bytes caps total size. This makes a topic a stream: an immutable, time-bounded history you can replay within the window. Audit logs, clickstream, and event-sourcing event stores use this. The replay window is the retention window.

Log compaction (cleanup.policy=compact): instead of deleting by age, Kafka guarantees it retains at least the latest value for every key, garbage-collecting superseded older values in the background. This makes a topic a table/changelog: the log is the full edit history, but its compacted tail is the current state of every key. A "current user profile" topic keyed by user_id is the canonical case. A brand-new consumer reads the compacted topic from offset 0 and materializes the entire current state without a database: how Kafka Streams rebuilds a KTable and how CDC pipelines bootstrap read models.

Check yourself

Pick the retention policy each topic needs.

Seven days of clickstream that analytics may replay within the window
Current user profile keyed by user_id, rebuildable by any new consumer
An audit log where every historical event must survive within its window
The changelog a Kafka Streams KTable restores its state store from
Compacted topic keyed by user_id, before compaction:
  (u1,"A") (u2,"X") (u1,"B") (u3,"Q") (u1,"C") (u2,"Y")
After compaction keeps latest per key:
  (u3,"Q") (u1,"C") (u2,"Y")   <- current state of every user

Deletes in a compacted topic use a tombstone: a record with the key and a null value. Compaction keeps the tombstone long enough for all consumers to observe the deletion, then removes both the tombstone and all prior values for that key.

Interview nuance: GDPR/right-to-erasure collides with long retention. An immutable 7-year audit stream cannot literally delete one user's records without breaking immutability, so the standard pattern is crypto-shredding: encrypt per-subject data with a per-user key and delete the key to render the data unrecoverable, rather than mutating the log. On a compacted topic, a tombstone plus compaction does the erasure directly.

Check yourself
A user invokes right-to-erasure against your immutable 7-year audit stream. What is the standard pattern?

Tiered storage (KIP-405, GA) decouples retention cost from broker disk: hot recent segments stay on local broker SSD; cold older segments offload to object storage (S3, GCS) transparently, and consumers reading old offsets fetch from object storage automatically. This makes cheap long or effectively infinite retention viable: 7 years of audit data at S3 prices instead of years of broker SSD, and brokers rebalance faster.

The subtle correctness trap: your dedup/idempotency window must be at least as long as the replay/retention window. If you keep 7 days of events but your consumer only remembers processed ids for 24 hours, replaying day-6 events sails past the dedup memory and double-applies them. Retention and dedup must be sized together.

Recap: delete-retention makes a topic a replayable stream bounded by its window; log compaction keeps the latest value per key and makes a topic a rebuildable table/changelog (with tombstones for deletes); tiered storage puts cold segments in object storage for cheap long retention; GDPR erasure on immutable logs uses crypto-shredding or tombstones; and the dedup window must be at least the replay window or replays double-apply.

Check yourself
A topic retains 7 days of events. The consumer's dedup store remembers processed ids for 24 hours. An incident forces a replay from 6 days back. What happens?

Apply

Your turn

The task this lesson builds to.

Design storage for two topics: an immutable audit event stream kept 7 years cheaply, and a 'current user profile' changelog; choose retention/compaction and storage tier for each.

Think about

  1. When do you use time/size retention vs log compaction?
  2. How does compaction give table/changelog semantics and enable state rebuild?
  3. How does tiered storage decouple retention cost from broker disk?

Practice

Make it stick

A second problem on the same idea, so it survives past today.

Design the retention and storage strategy for Netflix's viewing-history platform: an immutable 'play events' stream (billions/day) that data science replays for months, plus a 'current playback position per profile per title' changelog that the resume-watching feature reads with single-digit-ms latency. Choose policies, storage tiers, and handle a title being pulled from the catalog for legal reasons.

Think about

  1. Why is tiered storage mandatory rather than optional at billions/day?
  2. Where do you actually serve the single-digit-ms resume reads from?
  3. How do you remove a pulled title from each topic type without breaking immutability?