Pulsar was built with highly scalable persistent storage of message data as a primary objective. Pulsar topics enable you to persistently store as many unacknowledged messages as you need while preserving message ordering. By default, Pulsar stores all unacknowledged/unprocessed messages produced on a topic. Accumulating many unacknowledged messages on a topic is necessary for many Pulsar use cases but it can also be very time intensive for Pulsar consumers to “rewind” through the entire log of messages.
For a more practical guide to topic compaction, see the Topic compaction cookbook.
For some use cases, consumers don‘t need a complete “image” of the topic log. They may only need a few values to construct a more “shallow” image of the log, perhaps even just the most recent value. For these kinds of use cases, Pulsar offers topic compaction. When you run compaction on a topic, Pulsar goes through a topic’s backlog and removes messages that are obscured by later messages, i.e. topic compaction goes through the topic on a per-key basis and leaves only the most recent message associated with that key.
Pulsar's topic compaction feature:
Topic compaction example: the stock ticker
An example use case for a compacted Pulsar topic would be a stock ticker topic. On a stock ticker topic, each message bears a timestamped dollar value for stocks for purchase (with the message key holding the stock symbol, e.g.
AAPLorGOOG). With a stock ticker you may care only about the most recent value(s) of the stock and have no interest in historical data (i.e. you don‘t need to construct a complete image of the topic’s sequence of messages per key). Compaction would be highly beneficial in this case because it would keep consumers from needing to rewind through obscured messages.
When topic compaction is triggered via the CLI, it works in the following steps:
For each key that it encounters the compaction routine will keep a record of the latest occurrence of that key.
After that, the broker will create a new BookKeeper ledger and make a second iteration through each message on the topic. For each message:
If the key matches the latest occurrence of that key, then the key's data payload, message ID, and metadata will be written to the newly created ledger.
If the key doesn't match the latest then the message will be skipped and left alone.
If any given message has an empty payload, it will be skipped and considered deleted (akin to the concept of tombstones in key-value databases).
At the end of this second iteration through the topic, the newly created BookKeeper ledger is closed and two things are written to the topic's metadata:
Once this metadata is written compaction is complete.
After the initial compaction operation, the Pulsar broker that owns the topic is notified whenever any future changes are made to the compaction horizon and compacted backlog. When such changes occur:
Topic compaction behavior can be configured through various broker settings:
compactionRetainNullKey: Controls whether null keys are retained during compaction. When set to true, messages with null keys are preserved in the compacted ledger. When false (default), messages with null keys are treated as non-key messages and may be removed during compaction.
brokerServiceCompactionThreshold: The threshold size (in bytes) that triggers automatic compaction for a topic‘s backlog. When the topic’s backlog exceeds this size, compaction will be triggered automatically.
The compactionRetainNullKey parameter is particularly important for topics that contain messages without keys. This configuration determines how the compaction process handles such messages:
true): Messages with null keys are preserved during compaction, ensuring that unkeyed messages remain accessible in the compacted view.false): Messages with null keys may be removed during compaction, as they cannot be properly deduplicated without a key.This setting is useful for topics that mix keyed and unkeyed messages, allowing administrators to control whether unkeyed messages should be retained in the compacted topic.