Apache Kafka 4.4.0: What’s New & What It Means for Production Systems

|
Apache Kafka

TL;DR
Apache Kafka 4.4.0 was released on October 22, 2026, with 25 new KIPs and 963 commits since version 4.3.0. Three changes stand out for teams running Kafka in production: dead-letter queue support for share groups, improvements to KRaft cluster management, and transactional state stores in Kafka Streams. These changes give developers better options for handling failed records, simplify controller administration, and reduce the amount of state that must be replayed after a failure. The upgrade still requires careful planning, particularly around storage formatting, metadata versions, and application compatibility
Apache Kafka is widely used to move events between applications, services, and data systems. As these deployments grow, operational concerns become just as important as throughput. Teams need reliable ways to handle failed messages, manage cluster metadata, and recover stateful applications without unnecessary downtime.
Apache Kafka 4.4.0 addresses these concerns through a set of targeted improvements. Rather than introducing a completely different way to use Kafka, this release strengthens specific parts of the platform that affect day-to-day operations.
The most notable changes are dead-letter queues for share groups, updates to KRaft metadata management, and transactional state stores for Kafka Streams. Understanding these changes helps teams determine which features are relevant to existing workloads and what needs to be tested before upgrading.
Dead-Letter Queues for Share Groups (KIP-1191)
A message that repeatedly fails during processing can become a problem for the entire pipeline. It may need to be investigated, retried, or handled separately, while the rest of the workload continues to move forward.
Kafka 4.4.0 introduces dead-letter queue (DLQ) support for share groups. With this capability, records rejected by a share consumer or records that exceed the configured maximum delivery count can be directed to a designated DLQ topic. This gives teams a dedicated place to inspect failed records and decide what should happen next.
Previously, share groups did not provide this built-in DLQ mechanism. The new capability makes failure handling more explicit and gives operators a clearer path for investigating problematic records.
How DLQ Configuration Works
DLQ support requires the share group to use the appropriate feature version. In Kafka 4.4.0, the group must support share-group protocol version 2. Once that prerequisite is met, the relevant dynamic configuration determines how failed records are handled.
The principal settings include:
errors.deadletterqueue.topic.name specifies the DLQ topic.
errors.deadletterqueue.auto.create.topics.enable controls whether Kafka can create the DLQ topic automatically.
errors.deadletterqueue.group.enable controls DLQ group functionality on the relevant topic.
errors.deadletterqueue.copy.record.enable controls whether the original record's key and value are copied.
errors.deadletterqueue.topic.name.prefix provides a topic-name prefix for configurations that use prefix-based naming.
By default, the DLQ record contains metadata about the original record, such as its source topic, partition, offset, group ID, and delivery count. Copying the original key and value requires the corresponding option to be enabled.
Teams should verify the exact configuration scope and supported values in the Kafka 4.4 documentation before applying these settings to a production cluster.
Why This Matters
A DLQ does not automatically resolve a failed message. It makes the failure easier to isolate and investigate.
For example, a consumer processing order events might encounter a record with invalid data. Instead of leaving the team without a clear recovery path, the DLQ provides a place to inspect the failure, correct the underlying issue, and determine whether the record should be replayed.
This is particularly useful when share consumers process records from large workloads and failed messages need to be handled without losing visibility into the original event.
KRaft Improvements for Cluster Management
Kafka 4.x operates in KRaft mode, which uses Kafka's own metadata quorum instead of ZooKeeper. Kafka 4.4.0 builds on this architecture with changes to metadata bootstrapping, controller administration, and broker configuration.
Unified Metadata Bootstrapping (KIP-1170)
Kafka 4.4.0 changes how initial cluster metadata is written during storage formatting. The storage tool consolidates the initial metadata bootstrap information, replacing the previous arrangement that used a separate bootstrap.checkpoint.
The operational implication is important: storage directories formatted by kafka-storage are no longer forward-compatible. A broker must run the same version as, or a newer version than, the tool used to format its directory.
This means storage formatting needs to be treated as part of the cluster's version-management process. Teams should not assume that a directory formatted with a newer Kafka tool will work with an older broker. Before changing broker versions or reformatting storage, verify the supported procedure for the intended upgrade path.
Controller Unregistration (KIP-1312)
Kafka 4.4.0 adds a controller unregistration command and API. These allow operators to remove stale controller registrations from cluster metadata when a controller has been retired or its registration needs to be cleaned up.
The new command is:
kafka-cluster.sh unregister-controller <id>
The kafka-metadata-quorum.sh remove-controller command also supports the --unregister option. The operation is backed by the Admin.unregisterController API.
Controller unregistration requires metadata version 4.4-IV2. Operators should confirm that the cluster has the required metadata version before using the new functionality.
This change provides a more direct way to clean up controller metadata during cluster maintenance and reconfiguration.
Deprecation of broker.id
Kafka 4.4.0 also continues the move towards a consistent node identity model by deprecating the legacy broker.id configuration in favour of node.id in KRaft deployments.
Existing configurations that use broker.id may generate a deprecation warning. Teams maintaining Kafka configuration templates, automation, and deployment scripts should standardise on node.id and plan to remove the legacy setting before Kafka 5.0.
What These Changes Mean for Operators
Together, these changes make cluster administration more predictable, but they also reinforce the need for disciplined upgrade procedures. Storage formatting, metadata versions, and controller membership must be managed deliberately. A successful broker restart alone does not establish that every cluster-level change is safe.
Transactional State Stores in Kafka Streams (KIP-892)
Kafka Streams applications often maintain local state to support operations such as aggregations, joins, windowing, and interactive queries. When that state becomes large, restoring it after a failure can add significant recovery time.
Kafka 4.4.0 introduces transactional state stores, an opt-in capability that changes how state-store updates are handled.
Enable the feature with:
enable.transactional.statestores=true
When enabled, state-store writes are coordinated with the corresponding changelog transactions. Instead of wiping and rebuilding the entire state store after an error under exactly-once processing, Kafka Streams can discard uncommitted writes and replay the updates since the last successful commit.
The distinction matters for applications that maintain large amounts of local state. Rebuilding a store from its changelog can be expensive, while replaying a smaller set of recent updates can reduce the recovery work required.
Configuring Transactional State Stores
Kafka 4.4.0 introduces two settings that help control the new behaviour.
statestore.uncommitted.max.bytes sets the maximum amount of memory used to buffer uncommitted state-store records. The documented default is 64 MB per store. When the buffer limit is exceeded, Kafka Streams requests a task commit.
default.interactive.query.isolation.level controls the default isolation level for interactive queries. The default is READ_UNCOMMITTED, which allows queries to see uncommitted writes. Setting it to READ_COMMITTED makes those writes visible to interactive queries only after they have been committed.
The isolation setting is important for applications where query results must reflect committed state rather than intermediate updates.
What Changes During Recovery?
Consider a Kafka Streams application that maintains an aggregation over a large number of vehicle telemetry events. The application continuously updates local state and writes corresponding changes to its changelog topic.
If the application encounters an error, rebuilding the entire store can require replaying a substantial amount of historical data. With transactional state stores enabled, Kafka Streams can preserve committed state and replay the writes that were not committed successfully.
The benefit depends on the workload, the amount of uncommitted data, and the application's recovery characteristics. Transactional state stores do not guarantee a fixed recovery time, but they can avoid a full state-store rebuild in scenarios covered by the new behaviour.
Because the feature is opt-in, existing applications do not automatically switch to transactional state stores when upgrading to Kafka 4.4.0. Teams should enable it deliberately, validate the behaviour under failure conditions, and monitor recovery time and memory usage before adopting it in production.
Other Changes Worth Reviewing
The three features above are the main focus for teams evaluating Kafka 4.4.0, but the release includes other changes that may affect deployment and application behaviour.
The release and upgrade notes include updates to protocol message allocation limits, additional Linux I/O metrics exposed through JMX, and new configurations for tiered-storage replication lag. Kafka also introduces a client configuration for asynchronous DNS resolution of bootstrap servers. This behaviour is evolving, and Kafka Streams and Kafka Connect currently force the setting to its default synchronous behaviour for the clients they create internally.
Kafka Streams users should also review the compatibility notes for static membership with the Streams Rebalance Protocol. The relevant combination requires brokers and clients running Kafka 4.4 or newer. Downgrading brokers below 4.4 requires particular care if applications use group.instance.id with group.protocol=streams.
The full release notes and upgrade guide should be reviewed alongside application-specific tests. Not every change will affect every deployment, but compatibility details can matter when Kafka is part of a larger production system.
Upgrading to Apache Kafka 4.4.0
An upgrade should begin with a review of the current cluster configuration and the features the deployment intends to use. Kafka 4.4.0 supports server upgrades from versions 3.3.x through 4.3.0, subject to the documented compatibility and upgrade requirements.
Before upgrading, teams should check the following:
Review the cluster's starting version and operating mode. Kafka 4.x requires KRaft; ZooKeeper-based clusters must migrate to KRaft before upgrading to Kafka 4.x. Follow the documented migration and upgrade sequence rather than treating the upgrade as a simple binary replacement.
Validate storage formatting and metadata compatibility. Kafka 4.4.0 changes storage bootstrap behaviour. Use compatible kafka-storage tooling and follow the official instructions for the intended upgrade path. Check the required metadata version before using features such as controller unregistration.
Test share-group DLQs. Confirm that the share group supports the required feature version, the DLQ topic is configured correctly, and permissions and topic-creation settings are appropriate. Test rejected records and records that exceed their delivery limit, including how they are inspected and replayed.
Test Kafka Streams recovery. If transactional state stores are relevant, enable them in a staging environment first. Simulate failures, verify recovery behaviour, and assess memory consumption and interactive-query isolation settings. Do not assume that enabling the feature will produce the same recovery improvement for every workload.
Check application and client compatibility. Review Kafka Streams, Kafka Connect, client libraries, custom integrations, and deployment automation. Verify protocol and metadata versions, and test rollback or downgrade procedures against the documented limitations.
Monitor the cluster after the upgrade. Check broker health, consumer processing, task recovery, storage behaviour, and application-level latency. Validate the workloads that matter to the deployment before considering the upgrade complete.
The official Apache Kafka 4.4.0 upgrade guide and Kafka Streams 4.4 upgrade guide should be the primary references for planning these changes.
Building and Operating Kafka-Based Applications with Condense
Kafka provides the foundation for event streaming, but production applications often require more than a broker and a collection of consumers. Teams also need to integrate data sources, implement transformations, connect downstream systems, monitor individual services, and maintain the resulting applications.
Condense Runtime provides a managed runtime for event-driven applications. Applications can be assembled as pipelines comprising input connectors, transformations, and output connectors. Individual services have observability and alerts, while environment access is managed through the Condense Console.
For organisations that need implementation support, Digital Forward Deployed Engineers can work alongside internal teams to scope a use case, build and test the pipeline, deploy it, and support its operation and further development. The aim is to move a defined use case towards production without requiring the customer to treat the entire runtime setup as a separate platform-building project.
Condense Runtime can work with existing brokers through Broker Registry, including Apache Kafka, NATS, and Confluent Cloud. This makes it relevant to teams that want to build and operate event-driven applications around existing messaging infrastructure.
Kafka 4.4.0 introduces specific capabilities, including share-group DLQs and transactional state stores. Compatibility between these Kafka features and a particular Condense Runtime deployment should be validated against the supported broker versions and configuration before implementation.
For teams evaluating a production use case, a useful starting point is to define the data sources, required transformations, downstream applications, operational requirements, and success criteria. A focused use-case scoping session can establish the implementation approach and identify compatibility questions early.
Conclusion
Apache Kafka 4.4.0 focuses on practical improvements to reliability and operations. Share-group DLQs provide a clearer way to handle failed records, KRaft changes improve metadata and controller administration, and transactional state stores give Kafka Streams applications a way to reduce recovery work after failures.
The value of these changes depends on how a cluster and its applications are configured. A careful upgrade, targeted testing, and review of the official compatibility guidance remain essential.
For teams building Kafka-based applications, the next step is to look beyond the broker itself and consider how integrations, transformations, deployment, observability, and ongoing operations fit together. Condense Runtime provides a managed environment for building and operating event-driven applications, with implementation support for moving defined use cases towards production.
Official References
Frequently Asked Questions
Ready to Switch to Condense and Simplify Real-Time Data Streaming? Get Started Now!
Switch to Condense for a fully managed, Kafka-native platform with built-in connectors, observability, and BYOC support. Simplify real-time streaming, cut costs, and deploy applications faster.



