Skip to content

Releases: lisachenko/kafka-client

Release list

Release 4.4.0

Choose a tag to compare

@lisachenko lisachenko released this 30 Oct 19:18
d46d579

4.4.0 — Kafka 4.4.0 wire protocol

This release moves the client onto Apache Kafka 4.4.0 (released 2026-10-13). It implements everything Kafka 4.4 adds for clients, on top of the 4.x line (Kafka 4.0 to 4.3, the KIP-848 consumer protocol and the KIP-932 share consumer).

Requirements: PHP 8.4 or later and a Kafka 4.4 cluster (KRaft). Like every release of this package, the client sends the protocol versions of its Kafka release and does not negotiate down. Against brokers 4.0–4.3, stay on 4.3.1.

Highlights

  • Misrouted-connection detection, ApiVersions v5 (KIP-1242). The client sends the cluster id and node id it expects to reach. If the broker belongs to a different cluster or is a different node, it answers error 129. The client then drops the connection, calls the new Cluster::rebootstrap() to reload metadata from bootstrap.servers, and throws RebootstrapRequiredException. This applies to Client::apiVersions(), AdminClient::getApiVersions() and AdminClient::describeFeatures().
  • Transactional offset commits by topic id, TxnOffsetCommit v6 (KIP-1319). Inside a transaction of the v2 protocol, the producer names topics by id. It falls back to v5 for a topic without a known id, and to v4 for the v1 protocol. An unknown topic id (100) reloads the metadata. An unknown group (69) or a stale KIP-848 member epoch (113) makes the transaction abortable.
  • New AdminClient::unregisterController(int $controllerId) (KIP-1312). It sends the new UnregisterController api (key 94). An unknown id throws ControllerIdNotRegisteredException (136). It needs metadata.version 4.4-IV2.
  • Group deletion errors with a reason, DeleteGroups v3 (KIP-1331). deleteConsumerGroups() and deleteShareGroups() put the broker's per-group message into the exception context as error.
  • Share-group dead-letter queues (KIP-1191, share.version 2). This works with the existing KafkaShareConsumer: records it rejects, or that exceed the delivery count limit, are written to a dlq. topic. You configure it entirely through group and topic configs. See the new example examples/share-dead-letter-queue.php.
  • CIDR host patterns in ACLs (KIP-1276). createAcls() accepts hosts such as 10.0.0.0/8 or 2001:db8::/32 on a 4.4 cluster, and the authorizer matches clients against the block. No client change was needed; this is tested end to end.
  • New error codes: GroupDeletionFailedException (134), StreamsTopologyDescriptionUpdateFailedException (135) and ControllerIdNotRegisteredException (136).
  • Small behaviour fix: a KIP-848 consumer whose group was deleted now leaves without an exception, as the Java client does.

Breaking changes

  • TxnOffsetCommitRequest now needs topic ids. If you build it directly, pass the new $topicIds argument; without it the request throws UnknownTopicIdException before anything is sent. TxnOffsetCommitRequestV5 keeps the name-based frame. Code that only uses KafkaProducer::sendOffsetsToTransaction() is unaffected.
  • The client sends ApiVersions v5 and TxnOffsetCommit v6. A broker older than 4.4 refuses them; see Requirements above.

Not included

  • Streams groups (KIP-1071) are still out by decision. StreamsGroupHeartbeat/Describe v1 and the new StreamsGroupTopologyDescriptionUpdate api (key 93) are declared and probed, but have no client surface.

Verification

Everything was measured against a real Kafka 4.4.0 KRaft node:

  • 4252 unit and compliance tests pass.
  • 1183 integration tests pass on the PLAINTEXT, SSL, SASL_PLAINTEXT and SASL_SSL listeners, with no skips.
  • 1458 byte-exact wire vectors are replayed; 37 of them are new captures from the 4.4.0 node.

The full grammar, including what 4.4.0 changed and the broker quirks found along the way, is in docs/protocol/4.4.md. The full change list is in CHANGELOG.md under "Kafka 4.4 — Added/Changed".

Full diff: 4.3.1...4.4.0