Change the bootstrap server. Then use the client you already have.
These clients have been run against Camus: kafka-clients 4.4.0, librdkafka (confluent-kafka 2.16.1), and franz-go v1.22.0. A feature is listed here when at least one of them has exercised it. The compatibility doc records which one.
Produce and fetch
A producer appends record batches. A consumer fetches them by offset. An idempotent producer retries a sequence with the same producer id and epoch. The broker returns the original offset instead of appending the batch again, so a timeout followed by a retry does not duplicate that sequence.
A fetch is a page of the log from the offset you ask for. In the default isolation, you see batches that have been acknowledged. read_committed is stricter, and is described with transactions below.
Groups
Classic consumer groups join, sync, heartbeat, commit offsets, and leave. You can also list groups, describe one, and delete one. The Java client can set group.protocol=consumer, which uses the KIP-848 heartbeat instead of the classic join and sync.
Group authorization is not checked. Topic authorization is. A produce or fetch that fails an ACL returns TOPIC_AUTHORIZATION_FAILED (29) on that response, rather than hanging until the client times out.
Transactions
read_committed hides a batch until EndTxn commits it. An abort stays hidden. Camus does not write Kafka control-batch markers. Visibility is the committed and aborted offset ranges stored in metadata. A consumer in isolation level 1 simply does not receive offsets inside an open or aborted range.
A produce that arrives after the transaction is no longer ongoing is rejected with INVALID_TXN_STATE (48). The batch is not left visible.
Admin
The admin calls those three libraries actually make: describe cluster, describe and alter configs, create partitions, delete records, delete topics, and ACLs. Java has no non-incremental alter-configs in the client that was run. librdkafka has no offset-delete method and no transaction-admin API. franz-go has no describe-cluster. The compatibility table leaves a cell blank when that library cannot make the call, or when it has not been run.
Compaction
cleanup.policy=compact keeps the latest record for each key, at its original offset. Older values for that key are dropped from sealed extents. Compaction runs only when CAMUS_COMPACT_MS is greater than 0. It does not touch the unsealed tail. Tombstones are kept. There is no delete.retention.ms cleaner and no dirty-ratio trigger.
Differences that will surprise you
| Behavior | Camus |
|---|---|
acks=1 | Same barrier as acks=all. The broker does not acknowledge a batch that only one replica has seen, even if you asked for one. |
acks=0 | The broker does not wait. The batch may be lost. |
| A resource with no ACL | Allowed. Kafka's default is the opposite. Once an ACL matches, DENY beats ALLOW. Only host * matches. A more specific host is not consulted. |
| Produce or fetch denied | TOPIC_AUTHORIZATION_FAILED (29), not a timeout. |
DeleteRecords | Advances to the next whole object. It does not split a segment at an arbitrary offset. |
| Control batches | Not written. Transaction visibility is metadata ranges, not markers inside the log. |
The full list, including APIs that stay unimplemented, is in the compatibility doc.