5.2 Design principles — understand these and every method becomes obvious
This is the single most important operational fact in the chapter:
2.1 Asynchronous and eventually consistent
"Perhaps the most important thing to understand about Kafka's AdminClient is that it is asynchronous. Each method returns immediately after delivering a request to the cluster controller, and each method returns one or more
Futureobjects."
The wrapping hierarchy:
- wait until all topics are created
- check each topic's status individually
- retrieve the configuration of a specific topic after creation
⚠️ 2.2 Eventual consistency — the read-your-own-write trap
This is the single most important operational fact in the chapter:
The propagation arrow is the whole problem: at the moment the Future completes, a broker that is not yet aware of the new state can be the one that handles the read, so a listTopics request “may end up handled by a broker that is not up-to-date and will not contain a topic that was very recently created.” Eventually every broker will know about every topic, “but we can't guarantee exactly when.”
"Because Kafka's propagation of metadata from the controller to the brokers is asynchronous, the Futures that AdminClient APIs return are considered complete when the controller state has been fully updated. At that point, not every broker might be aware of the new state, so a
listTopicsrequest may end up handled by a broker that is not up-to-date and will not contain a topic that was very recently created. This property is also called eventual consistency: eventually every broker will know about every topic, but we can't guarantee exactly when."
Practical rule: never write createTopics(...).get(); listTopics(...) and assert. Never write deleteTopics(...).get() and assert absence. Retry-with-backoff, or accept the ambiguity.
2.3 Which broker handles what — and why it matters when debugging
Reads are “directed to the least-loaded broker (based on what the client knows).” This “shouldn't impact you as an API user, but it can be good to know in case you are seeing unexpected behavior, you notice that some operations succeed while others fail, or if you are trying to figure out why an operation is taking too long.” Writes all funnel through one node; reads spray across the cluster — so a sick controller breaks every mutation while every read still looks fine.
"This shouldn't impact you as an API user, but it can be good to know in case you are seeing unexpected behavior, you notice that some operations succeed while others fail, or if you are trying to figure out why an operation is taking too long."
That's the debugging hook: writes all funnel through one node (the controller), reads spray across the cluster. A sick controller breaks all mutations while all reads look fine.
2.4 Options objects
"Every method in AdminClient takes as an argument an
Optionsobject specific to that method" —listTopics→ListTopicsOptions,describeCluster→DescribeClusterOptions.
The universal setting: timeoutMs
"this controls how long the client will wait for a response from the cluster before throwing a
TimeoutException. This limits the time in which your application may be blocked by an AdminClient operation."
Other examples: whether listTopics should also return internal topics; whether describeCluster should also return which operations the client is authorized to perform on the cluster.
2.5 Flat hierarchy — a deliberate, "controversial" choice
"All admin operations supported by the Apache Kafka protocol are implemented in
KafkaAdminClientdirectly. There is no object hierarchy or namespaces. This is a bit controversial as the interface can be quite large and perhaps a bit overwhelming, but the main benefit is that if you want to know how to programmatically perform any admin operation on Kafka, you have exactly one JavaDoc to search, and your IDE autocomplete will be quite handy. You don't have to wonder whether you are just missing the right place to look. If it isn't in AdminClient, it was not implemented yet."
2.6 🚫 Never touch ZooKeeper directly
"At the time we are writing this chapter (Apache Kafka 2.5 is about to be released), most admin operations can be performed either through AdminClient or directly by modifying the cluster metadata in ZooKeeper. We highly encourage you to NEVER use ZooKeeper directly, and if you absolutely have to, report this as a bug to Apache Kafka."
The reason is a forward-compatibility argument, not a stylistic one:
The community will remove the ZooKeeper dependency (→ KRaft).
| Your app talks to… | What the migration costs you |
|---|---|
| ZooKeeper directly | Must be modified |
| AdminClient | API remains exactly the same, “just with a different implementation inside the Kafka cluster” |
AdminClient is the abstraction that makes the ZooKeeper→KRaft migration invisible to your code. That is its most underrated value.
5.1 What problem does AdminClient solve?
The book is honest about the trade-off: "The second alternative has downsides, but avoiding the dependency on an additional process to generate topics is an attractive feature in…
5.3 Lifecycle: create, configure, close
Introduced in Kafka 2.1.0. Default behavior: "Kafka validates, resolves, and creates connections based on the hostname provided in the bootstrap server configuration (and later in…