For the latest stable version, please use Korvet 0.19!

Topic Management

This guide covers creating and managing topics in Korvet.

Topic defaults — including auto-create — are configured via the pattern list under korvet.topics. Each entry’s name is a glob pattern matched against topic names; entries are evaluated in declared order and combined first-match-wins per field.

Creating Topics

Automatic Topic Creation

By default, topics are not automatically created when you first produce to them or request metadata for them. Auto-creation is configured per pattern under korvet.topics:

korvet:
  topics:
    - name: "*"
      auto-create: false  # Enable/disable automatic topic creation (default: false)
      partitions: 1       # Default partitions for auto-created topics (default: 1)

When auto-creation is disabled, you must explicitly create topics before using them.

Explicit Topic Creation

You can create topics explicitly with standard Kafka tooling or with the bundled korvet-cli.

Using korvet-cli topics

korvet-cli topics mirrors kafka-topics syntax. It is a thin wrapper over the Kafka AdminClient and passes --config key=value pairs through verbatim. The only Korvet-specific topic config is offset.sequence.bits; all other accepted keys are standard Kafka topic configs such as retention.ms and segment.ms.

korvet-cli topics --bootstrap-server localhost:9092 \
  --create \
  --topic my-topic \
  --partitions 3 \
  --config retention.ms=604800000 \
  --config offset.sequence.bits=14 \
  --config segment.ms=3600000
--replication-factor is accepted for compatibility but ignored, as Korvet uses Redis for storage and replication.

Using kafka-topics

Upstream Kafka CLI tooling works for standard Kafka topic configs:

kafka-topics --bootstrap-server localhost:9092 \
  --create \
  --topic my-topic \
  --partitions 3 \
  --replication-factor 1

Creating Topics with the offset.sequence.bits Configuration

The upstream kafka-topics CLI performs client-side validation and rejects the Korvet-specific offset.sequence.bits config with an Unknown topic config name error.

Use korvet-cli topics (a thin AdminClient wrapper that does not validate config names client-side) when you want to set offset.sequence.bits, or use the Kafka AdminClient API directly.

To set offset.sequence.bits with upstream Kafka tooling, use the Kafka AdminClient API, which does not perform client-side validation:

Properties props = new Properties();
props.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");

try (AdminClient admin = AdminClient.create(props)) {
    NewTopic topic = new NewTopic("my-topic", 3, (short) 1);
    topic.configs(Map.of(
        "offset.sequence.bits", "14",
        "retention.ms", "604800000"
    ));
    admin.createTopics(List.of(topic)).all().get();
}

Accepted topic configurations:

The broker accepts only the following topic config keys. Any other key (including value.type and storage.compression) is rejected with INVALID_CONFIG ("Unknown or unsupported topic config").

  • retention.ms - Total time-based retention in milliseconds (across all tiers)

  • retention.bytes - Total size-based retention in bytes

  • segment.ms - Duration of each local stream bucket in milliseconds. Optional. Must be positive and less than the effective local retention window.

  • segment.bytes - Size of each local stream bucket in bytes

  • compression.type - Compression for Kafka fetch responses (none, gzip, snappy, lz4, zstd). Default: none

  • cleanup.policy - Only delete is supported. compact and delete,compact are rejected (log compaction is not implemented).

  • offset.sequence.bits - Bits reserved for the per-millisecond sequence component in Korvet offsets. Range: 1-16. Default: 14. Settable only at topic creation; cannot be altered.

  • storage.compression.type - Codec for compressing the record value at rest in Redis (none, gzip, snappy, lz4, zstd). Unset inherits the server-level korvet.storage.local.compression.codec. Setting it to none stores the value uncompressed so non-Kafka clients can read it directly via XRANGE. Settable only at topic creation; cannot be altered.

Tiered storage configurations (when remote storage is enabled at server level):

  • remote.storage.enable - Enable tiered storage for this topic (Kafka KIP-405). Default: false

  • local.retention.ms - Time to keep in the local tier before Redis data expires. -2 = use retention.ms (Kafka KIP-405)

  • local.retention.bytes - Size to keep in the local tier before Redis trimming falls back to retention.bytes. -2 = use retention.bytes (Kafka KIP-405)

At-rest compression of the record value is set per topic via storage.compression.type (falling back to the server-level korvet.storage.local.compression.codec, default lz4). This is distinct from the Kafka-facing compression.type, which only affects fetch-response compression.

Listing Topics

List all topics:

kafka-topics --bootstrap-server localhost:9092 --list

Describing Topics

Get details about a topic:

kafka-topics --bootstrap-server localhost:9092 \
  --describe \
  --topic my-topic

Deleting Topics

Delete a topic:

kafka-topics --bootstrap-server localhost:9092 \
  --delete \
  --topic my-topic

Altering Topic Configuration

Topics can be configured with:

  • Partitions: Number of partitions for parallelism (set during creation only)

  • Retention: Time-based (retention.ms) and size-based (retention.bytes) retention policies

  • Protocol Compression: Compression for Kafka fetch responses (compression.type)

  • At-Rest Compression: Codec for the record value stored in Redis (storage.compression.type, create-time only)

  • Offset Encoding: Per-topic offset sequence width (offset.sequence.bits, create-time only)

  • Bucketing: Time-bucketed local streams (segment.ms, segment.bytes)

Using kafka-configs CLI

Use korvet-cli topics --alter or kafka-configs to alter topic configurations.

korvet-cli topics --bootstrap-server localhost:9092 \
  --alter \
  --topic my-topic \
  --config retention.ms=604800000 \
  --config segment.ms=1800000
kafka-configs --bootstrap-server localhost:9092 \
  --entity-type topics \
  --entity-name my-topic \
  --alter \
  --add-config retention.ms=604800000,compression.type=lz4
offset.sequence.bits cannot be altered after topic creation; it is settable only at creation time.

Using AdminClient API

Alternatively, use the AdminClient API:

ConfigResource topicResource = new ConfigResource(ConfigResource.Type.TOPIC, "my-topic");
List<AlterConfigOp> ops = List.of(
    new AlterConfigOp(new ConfigEntry("retention.ms", "604800000"), AlterConfigOp.OpType.SET),
    new AlterConfigOp(new ConfigEntry("compression.type", "lz4"), AlterConfigOp.OpType.SET)
);
admin.incrementalAlterConfigs(Map.of(topicResource, ops)).all().get();

See Redis Streams storage for details on how records are stored.

Describing Topic Configuration

View current topic configuration using korvet-cli topics --describe or kafka-configs --describe:

korvet-cli topics --bootstrap-server localhost:9092 \
  --describe \
  --topic my-topic
kafka-configs --bootstrap-server localhost:9092 \
  --entity-type topics \
  --entity-name my-topic \
  --describe

Protocol compression types (compression.type):

  • none - No compression (default)

  • gzip - Good compression ratio, higher CPU usage

  • snappy - Balanced compression and speed

  • lz4 - Fast compression, lower CPU usage

  • zstd - Best compression ratio, moderate CPU usage

At-rest compression in Redis is set per topic via storage.compression.type (create-time only), falling back to the server-level korvet.storage.local.compression.codec (default lz4). It is independent of the Kafka-facing compression.type, which only affects fetch-response compression. Set storage.compression.type=none to keep values directly readable by non-Kafka clients.

See Compression for more details on protocol compression.

Tiered Storage Configuration

When tiered storage is enabled at the server level, you can configure per-topic retention policies to control when data moves between tiers.

Configuring Tiered Storage with AdminClient API

Use the AdminClient API to configure tiered storage (since kafka-configs --alter is not supported):

NewTopic topic = new NewTopic("my-topic", 3, (short) 1);
topic.configs(Map.of(
    "remote.storage.enable", "true",
    "retention.ms", "31536000000",           // 1 year total
    "local.retention.ms", "86400000"         // 1 day in local tier
));
admin.createTopics(List.of(topic)).all().get();

This configures:

  • Local tier: 1 day (local.retention.ms=86400000)

  • Remote tier: ~364 days (implicit: retention.ms - local.retention.ms)

  • Total retention: 1 year (retention.ms=31536000000)

Tiered Storage Configuration Reference

Configuration Default Description

remote.storage.enable

false

Enable tiered storage for this topic (Kafka KIP-405)

local.retention.ms

-2

Time to keep in the local tier before Redis data expires. -2 = use total retention.ms

local.retention.bytes

-2

Size to keep in the local tier before Redis trimming falls back to retention.bytes. -2 = use total retention.bytes

retention.ms

604800000

Total retention across all tiers (7 days default)

Remote tier retention is implicit and calculated as retention.ms - local.retention.ms. Data is deleted after the total retention.ms period.

See Remote Storage for server-level tiered storage configuration.