Kafka Broker and KRaft Config Generator
A KRaft server.properties, with the listener
wiring and the internal topic replication both sized for the cluster you
actually have.
server.properties
updates as you type Common mistakes
These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.
Running one broker with default internal topic settings
__consumer_offsets and the transaction log default to a replication factor of three. On a single broker they cannot be created and consumers fail with a confusing error.
Instead:Set offsets.topic.replication.factor and transaction.state.log.replication.factor to 1 for a single-broker setup.
Setting min.insync.replicas equal to the replication factor
One broker restarting then stops all acks=all writes. There is no headroom for routine maintenance.
Instead:min.isr = RF - 1.
Leaving auto.create.topics.enable on
A typo in a topic name silently creates a topic with default partitions and replication, which then looks like data loss.
Instead:Turn it off outside development.
Where a KRaft broker config goes wrong
Almost all of it is the listener wiring, plus one default that breaks every small cluster.
The internal topics default to replication factor 3
offsets.topic.replication.factor, transaction.state.log.replication.factor and transaction.state.log.min.isr all default to values a one or two broker cluster cannot satisfy. Nothing fails at startup: the broker comes up healthy, and then the first consumer to connect cannot have __consumer_offsets created for it and fails with an error about that topic rather than about the broker count. This generator caps them at the cluster size for exactly that reason.
controller.quorum.voters is id@host:port
The node id is part of each entry and it is not optional. A plain host:port list produces a quorum that never forms, and the broker log fills with controller connection messages that never say the format is wrong. Each id has to match that controller's own node.id, and the voter set is fixed at format time unless you are on 3.9 or later with dynamic quorums.
listeners is what it binds, advertised.listeners is what clients are told
Binding 0.0.0.0 is correct and advertising it is not, because every client would then try to connect to 0.0.0.0. The advertised address has to be one the client can resolve and reach, which inside Kubernetes means the pod's own stable address, and that is why a Kafka StatefulSet exists rather than a Deployment.
The controller listener carries Raft and nothing else
inter.broker.listener.name must name a different listener from the one in controller.listener.names. Pointing broker traffic at the controller listener fails validation at startup. A combined-role node runs both listeners on different ports for this reason, and a controller-only node has no broker listener at all.
What this cannot see
It does not know your hardware, your topic count or your throughput, so nothing here is a capacity decision: the cluster sizing calculator on this site answers how many brokers, and the disk calculator answers how much storage. It also cannot format your storage directory, which has to happen before the first start with kafka-storage.sh and a cluster id shared by every node.