Which authorizer class do you configure for ACLs on a modern KRaft cluster versus a legacy ZooKeeper cluster, and how does ACL storage differ?
answer
- KRaft → StandardAuthorizer (org.apache.kafka.metadata.authorizer)
- ZK → AclAuthorizer (kafka.security.authorizer)
- old: SimpleAclAuthorizer
- KRaft stores ACLs in __cluster_metadata log
- ZK stores ACLs in znodes + watches
- authorizer.class.name config
basics
~10 sOn KRaft set authorizer.class.name to StandardAuthorizer; on legacy ZooKeeper clusters use AclAuthorizer (formerly SimpleAclAuthorizer). KRaft stores ACLs in the metadata log; ZooKeeper-based authorizers store them in ZooKeeper.
solid answer
~40 sFor a KRaft cluster you set `authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer`. For a legacy ZooKeeper-based cluster you use `kafka.security.authorizer.AclAuthorizer` (which replaced the older `SimpleAclAuthorizer`). The big architectural difference is storage and distribution: AclAuthorizer persists ACLs in ZooKeeper and brokers watch ZK znodes for changes; StandardAuthorizer stores ACLs as records in the KRaft **metadata log** (`__cluster_metadata`), so every broker and controller replicates them through the same Raft replication that carries all cluster metadata — no ZooKeeper dependency. Both implement the same `Authorizer` interface and the same ACL semantics (operation x resource matrix, prefixed/wildcard patterns, DENY-over-ALLOW), so the kafka-acls CLI and AdminClient behave identically. StandardAuthorizer also surfaces an early-start/standby state so the controller can come up before all ACLs have replayed.
go deeper
Know there's a config (authorizer.class.name) that turns on ACL enforcement.
Match KRaft→StandardAuthorizer and ZK→AclAuthorizer and know each by name.
Explain the storage/propagation difference (metadata log vs ZK watches) and that semantics are identical.
Reason about migration, early-start ACL loading, and operational implications of metadata-log-based ACL replication.
## The two implementations Kafka's pluggable authorization is the `Authorizer` interface. Two built-in implementations matter: - **StandardAuthorizer** — `org.apache.kafka.metadata.authorizer.StandardAuthorizer`. The authorizer for **KRaft** mode (the post-ZooKeeper architecture). - **AclAuthorizer** — `kafka.security.authorizer.AclAuthorizer`. The authorizer for **legacy ZooKeeper** clusters. It superseded the even older `kafka.security.auth.SimpleAclAuthorizer` (the deprecated `kafka.security.auth.Authorizer` package). You choose one via the broker config `authorizer.class.name`. Absent that config, no authorizer runs and everything is allowed. ## Storage and propagation — the real difference **AclAuthorizer (ZK):** ACLs live in ZooKeeper znodes. Brokers register ZK watches; when an ACL changes, ZK notifies brokers and they refresh their in-memory cache. Consistency and availability of ACLs are tied to ZooKeeper. **StandardAuthorizer (KRaft):** ACLs are ordinary metadata records in the **KRaft metadata log** (the `__cluster_metadata` topic). They replicate through Raft exactly like topic/partition/config metadata. Every broker and controller applies these records to build the same in-memory ACL view. There's no ZooKeeper; ACL changes go through the controller as metadata writes. ## Same semantics, same tools Because both implement the identical `Authorizer` contract, the authorization *behavior* is the same: the operation x resource-type matrix, LITERAL/PREFIXED/wildcard patterns, and DENY-over-ALLOW precedence are unchanged. `kafka-acls.sh` and `AdminClient.createAcls/deleteAcls/describeAcls` work the same way against either — you just point them at the bootstrap servers. ## KRaft-specific operational notes - StandardAuthorizer tracks whether it has finished loading ACLs from the log; during early startup it can operate in a restrictive/standby state until the metadata catches up, so the controller isn't blocked. - Because ACLs are in the metadata log, they benefit from the same snapshotting and replay machinery as all other cluster metadata. ## Migration note During ZK-to-KRaft migration, ACLs are migrated from ZooKeeper into the metadata log so the StandardAuthorizer can serve them post-migration. ## What stays out of scope here The defaults `super.users` and `allow.everyone.if.no.acl.found` apply to both authorizers but are covered by a sibling topic; here the focus is the class choice and storage model.
- Where are ACLs physically stored under StandardAuthorizer?As metadata records in the KRaft metadata log (__cluster_metadata), replicated via Raft to all brokers/controllers — no ZooKeeper involved.
- Does switching authorizers change ACL semantics like DENY-over-ALLOW?No. Both implement the same Authorizer interface, so the matrix, prefixed/wildcard patterns, and DENY precedence are identical; only storage/propagation differs.
saying these in an interview costs you the question
- Saying KRaft still uses ZooKeeper to store ACLs — it uses the metadata log.
- Naming AclAuthorizer for a KRaft cluster, or StandardAuthorizer for a pure ZK cluster.
- Claiming semantics differ between authorizers — only storage/propagation does.
- Forgetting that with no authorizer.class.name configured, no authorization happens at all.