<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Zeliot </title>
    <description>The latest articles on DEV Community by Zeliot  (zeliotofficial).</description>
    <link>https://dev.to/zeliotofficial</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F2710%2Fd31008f8-2415-45c7-81bb-fbc19ad30ca7.png</url>
      <title>DEV Community: Zeliot </title>
      <link>https://dev.to/zeliotofficial</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zeliotofficial"/>
    <language>en</language>
    <item>
      <title>Kafka Partition Strategy: The Complete Guide to Designing for Scale from Day One</title>
      <dc:creator>Sachin Kamath</dc:creator>
      <pubDate>Tue, 21 Jul 2026 07:40:42 +0000</pubDate>
      <link>https://dev.to/zeliotofficial/kafka-partition-strategy-the-complete-guide-to-designing-for-scale-from-day-one-3eh9</link>
      <guid>https://dev.to/zeliotofficial/kafka-partition-strategy-the-complete-guide-to-designing-for-scale-from-day-one-3eh9</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Kafka partition strategy is one of the most important architectural decisions when building scalable event-driven applications. It determines how data is distributed across partitions, sets the upper limit for consumer parallelism, influences message ordering, and directly impacts throughput, broker utilization, and cluster performance. Choosing the right Kafka partition count and partition key from the start helps prevent hotspots, balance workloads, and simplify future scaling. Condense is a Kafka-native unified data streaming platform that simplifies the entire partition lifecycle through Kafka Management, enabling engineering teams to configure partitions during topic creation, scale partition counts as workloads grow, monitor partition health and consumer lag, inspect partition-level data, and manage rebalancing from a unified interface. This guide explains how to design an effective Kafka partition strategy, calculate the right partition count, choose the right partition key, avoid common partitioning mistakes, and scale topics confidently in production&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Apache Kafka is designed to scale horizontally, but that scalability depends on one fundamental architectural decision: the partition strategy. Every topic in Kafka is divided into partitions, which determine how data is distributed across brokers, how many consumers can process events in parallel, and whether related events maintain their ordering. A well-designed partition strategy enables applications to scale predictably as data volumes grow, while a poor strategy can create bottlenecks that become increasingly difficult to resolve in production.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Partition strategy extends beyond simply deciding how many partitions a topic should have. It involves calculating the right partition count based on throughput requirements, selecting partition keys that balance workloads without compromising ordering guarantees, avoiding hotspots caused by uneven data distribution, and planning for future growth. Since partitioning decisions influence producers, consumers, stream processing applications, and downstream systems, modifying them after deployment often requires careful migration planning.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;While Apache Kafka provides the flexibility to configure and scale partitions, managing them across production environments introduces additional operational complexity. Condense simplifies this process through its Kafka Management capabilities, allowing engineering teams to configure partition counts during topic creation, increase partitions as workloads grow, inspect partition-level data, monitor consumer lag and partition assignments, and manage consumer rebalancing from a unified interface. This enables teams to implement and operate scalable partition strategies more efficiently while continuing to leverage the flexibility of Apache Kafka.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;In this guide, we'll explore why Kafka partition strategy is one of the most important design decisions in event streaming, how to calculate the right partition count, design effective partition keys, prevent hotspots, and safely scale partitions as application workloads evolve.&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Is Kafka Partition Strategy the Most Consequential Design Decision?&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Every Kafka topic is divided into one or more partitions, making partitions the fundamental unit of scalability, parallel processing, and fault tolerance. As records are written to a topic, Kafka distributes them across these partitions, allowing producers and consumers to process data concurrently. Because of this, the partition strategy directly influences application throughput, consumer parallelism, message ordering, broker utilization, and the overall efficiency of the Kafka cluster.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Unlike configuration settings such as retention policies, compression, or replication factors, partitioning decisions become deeply integrated into application architecture. Producers determine how records are distributed using partition keys, consumers process records based on partition assignments, and stateful stream processing applications rely on consistent partitioning to maintain local state and perform joins or aggregations. Changing the partition strategy after applications are deployed often requires creating new topics, migrating producers and consumers, and validating downstream processing, making it one of the most expensive architectural changes in a Kafka deployment.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;A well-designed partition strategy delivers several benefits:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Maximizes producer and consumer throughput&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enables horizontal scaling through partition-level parallelism&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Preserves message ordering for related events&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Balances workload evenly across brokers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reduces the risk of hotspots and consumer bottlenecks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simplifies long-term capacity planning&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conversely, a poorly designed strategy can create challenges that become more pronounced as workloads grow. Topics with too few partitions restrict consumer parallelism, ineffective partition keys create uneven workload distribution, and insufficient planning for future growth can force disruptive repartitioning efforts in production.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Although partition strategy is an architectural decision, implementing and managing that strategy at scale requires operational visibility. Condense simplifies Kafka partition management through its Kafka Management capabilities, enabling engineering teams to configure partitions during topic creation, increase partition counts as workloads grow, monitor partition health and consumer lag, inspect partition-level messages, and manage consumer group rebalancing from a unified interface. This allows teams to focus on designing the right partition strategy while simplifying its implementation and ongoing operation.&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Key Takeaways&lt;/strong&gt;&amp;nbsp;
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Kafka Partition Strategy Influences&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Why It Matters&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Consumer Parallelism&lt;/td&gt;
&lt;td&gt;Determines the maximum number of active consumers in a consumer group&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Throughput&lt;/td&gt;
&lt;td&gt;Controls how much data producers and consumers can process concurrently&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Message ordering&lt;/td&gt;
&lt;td&gt;Preserves the sequence of related events within a partition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Broker Utilization&lt;/td&gt;
&lt;td&gt;Distributes storage and processing workloads across the cluster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scalability&lt;/td&gt;
&lt;td&gt;Enables topics to grow with increasing data volumes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operational Complexity&lt;/td&gt;
&lt;td&gt;Poor partitioning decisions are difficult and costly to change after deployment&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How Does Kafka Partition Count Determine Consumer Parallelism?&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;One of Kafka's biggest strengths is its ability to process large volumes of data in parallel. However, the level of parallelism that a Kafka application can achieve is determined by a single factor: &lt;strong&gt;the number of partitions in a topic&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Each partition acts as an independent, ordered log that can be processed by only one consumer within a consumer group at any given time. This guarantees message ordering within the partition while allowing multiple partitions to be processed simultaneously by different consumers. As a result, the number of partitions defines the maximum number of consumers that can actively process records in parallel.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Consumer Parallelism in Action&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Consider a Kafka topic with four partitions.&amp;nbsp;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Topic Partitions&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Consumers in the Consumer Group&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Active Consumers&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Idle Consumers&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;With four partitions:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Two consumers process two partitions, leaving two partitions assigned across the available consumers.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Four consumers can each process one partition simultaneously.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adding more than four consumers does not increase throughput because there are no additional partitions to assign.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This limitation is commonly referred to as the consumer parallelism ceiling. Regardless of how many application instances are deployed, a consumer group cannot process records in parallel beyond the number of partitions available in the topic.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Why Consumer Parallelism Matters&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Imagine a connected mobility platform ingesting telemetry from hundreds of thousands of vehicles. As more vehicles come online, the volume of incoming events increases significantly. If the telemetry topic has only four partitions, only four consumers can actively process those events at any given time. Deploying additional consumer instances does not improve throughput because the partition count limits parallel processing.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;By increasing the partition count, Kafka can distribute the workload across more consumers, allowing the application to scale horizontally as data volumes grow.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;More Partitions Don't Always Mean Better Performance&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Although increasing the number of partitions enables greater consumer parallelism, creating excessive partitions introduces additional operational overhead. Every partition consumes broker resources, increases metadata management, extends consumer group rebalancing, and adds complexity to cluster operations.&lt;/p&gt;

&lt;p&gt;The goal is to provision enough partitions to support current and future workloads without creating unnecessary operational overhead.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;How Condense Simplifies Partition Scaling&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;As applications evolve, maintaining the right balance between partition count and consumer parallelism becomes an ongoing operational task. Condense simplifies this through Kafka Management, allowing engineering teams to configure partition counts during topic creation and increase partitions as workloads grow. Combined with partition-level observability, consumer lag monitoring, and consumer group health tracking, teams can validate whether additional partitions are improving throughput and parallelism without manually correlating broker-level metrics.&amp;nbsp;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Best Practice:&lt;/strong&gt; Size Kafka topics based on the maximum consumer parallelism your application is expected to require over time, not just the number of consumers deployed today. As workloads grow, periodically review partition utilization and consumer lag to determine whether increasing the partition count is necessary.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How Do You Calculate the Right Kafka Partition Count?&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Choosing the right Kafka partition count is one of the most important capacity planning decisions when designing an event streaming platform. Too few partitions can limit throughput and consumer parallelism, while too many increase broker overhead, metadata management, and operational complexity. Instead of relying on fixed recommendations, partition count should be determined using expected throughput, consumer processing capacity, and future growth projections.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;A commonly used approach is to calculate the partition count based on both producer and consumer throughput requirements and choose the larger value.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Kafka Partition Count Formula&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;br&gt;
&amp;nbsp;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Partition&lt;/span&gt; &lt;span class="nx"&gt;Count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Max &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;&amp;nbsp;&lt;/span&gt;
&lt;span class="err"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt; &lt;span class="nx"&gt;Target&lt;/span&gt; &lt;span class="nx"&gt;Producer&lt;/span&gt; &lt;span class="nx"&gt;Throughput&lt;/span&gt; &lt;span class="err"&gt;÷&lt;/span&gt; &lt;span class="nx"&gt;Producer&lt;/span&gt; &lt;span class="nx"&gt;Throughput&lt;/span&gt; &lt;span class="nx"&gt;per&lt;/span&gt; &lt;span class="nx"&gt;Partition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;&amp;nbsp;&lt;/span&gt;
&lt;span class="err"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt; &lt;span class="nx"&gt;Target&lt;/span&gt; &lt;span class="nx"&gt;Consumer&lt;/span&gt; &lt;span class="nx"&gt;Throughput&lt;/span&gt; &lt;span class="err"&gt;÷&lt;/span&gt; &lt;span class="nx"&gt;Consumer&lt;/span&gt; &lt;span class="nx"&gt;Throughput&lt;/span&gt; &lt;span class="nx"&gt;per&lt;/span&gt; &lt;span class="nx"&gt;Partition&lt;/span&gt;&lt;span class="err"&gt;&amp;nbsp;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;&amp;nbsp;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Target Producer Throughput&lt;/strong&gt; is the expected rate at which data is produced.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Producer Throughput per Partition&lt;/strong&gt; is the maximum throughput a single partition can sustain.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Target Consumer Throughput&lt;/strong&gt; is the rate at which data must be processed.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consumer Throughput per Partition&lt;/strong&gt; is the maximum processing capacity of a single partition.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Example Calculation&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Consider a real-time streaming application with the following requirements:&amp;nbsp;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Metric&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Target throughput&lt;/td&gt;
&lt;td&gt;600 MB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Producer throughput per partition&lt;/td&gt;
&lt;td&gt;50 MB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Consumer throughput per partition&lt;/td&gt;
&lt;td&gt;30 MB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Producer calculation:&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;600 ÷ 50 = 12 partitions&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consumer calculation:&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;600 ÷ 30 = 20 partitions&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recommended partition count:&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Max(12, 20) = 20 partitions&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Although producers can achieve the required throughput with 12 partitions, consumers require 20 partitions to process data without creating bottlenecks. In this scenario, &lt;strong&gt;20 partitions&lt;/strong&gt; is the appropriate starting point.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Factors That Influence Partition Count&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;There is no universal recommendation for the ideal number of Kafka partitions. The optimal partition count depends on several workload-specific factors, including:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Message size&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Producer batching and compression&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Replication factor&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Acknowledgement (acks) configuration&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consumer processing complexity&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Broker CPU, memory, and storage performance&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expected traffic growth&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maximum consumer parallelism&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Benchmarking representative workloads is significantly more reliable than relying on generic partition sizing recommendations.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Plan for Growth, Not Just Today's Traffic&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Kafka allows partition counts to be increased after a topic is created, but increasing partitions changes how future records are distributed across the topic. While this makes scaling possible, resizing production topics still requires planning, especially for applications that depend on key-based routing or message ordering.&lt;/p&gt;

&lt;p&gt;A better approach is to estimate expected workload growth over the next two to three years and provision enough partitions to support that scale from the beginning. This reduces the need for repartitioning as applications evolve.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;How Condense Simplifies Partition Planning&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Once the required partition count has been determined, &lt;strong&gt;Condense&lt;/strong&gt; simplifies implementation through &lt;strong&gt;Kafka Management&lt;/strong&gt;. Engineering teams can configure partition count, replication factor, retention policies, cleanup policies, and segment settings when creating a topic from a unified interface. As workloads grow, partition counts can be increased without recreating the topic, allowing streaming applications to scale while continuing to operate on the same Kafka deployment. Combined with partition-level observability and consumer lag monitoring, teams can validate whether additional partitions are delivering the expected improvements in throughput and parallelism.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practice:&lt;/strong&gt; Calculate Kafka partition count using measured throughput, expected consumer parallelism, and future growth projections. Configure topics with sufficient partitions during initial deployment, and periodically review partition utilization as workloads evolve.&amp;nbsp;&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Should You Design a Kafka Partition Key?&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Choosing the right Kafka partition count determines how much a topic can scale, but choosing the right &lt;strong&gt;partition key&lt;/strong&gt; determines &lt;strong&gt;how efficiently that scale is utilized&lt;/strong&gt;. The partition key controls how records are distributed across partitions, whether related events remain ordered, and how evenly workloads are balanced across brokers and consumers. An ineffective partition key can create hotspots, uneven resource utilization, and reduced application throughput even when a topic has an adequate number of partitions.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;When a producer sends a record with a key, Kafka uses a hashing algorithm to determine the destination partition.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Partition = hash(partition_key) % number_of_partitions&lt;/code&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;This calculation ensures that every record with the same partition key is consistently routed to the same partition, preserving message ordering for that key.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Why Does the Partition Key Matter?&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;The partition key influences several critical aspects of a Kafka deployment:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Distribution of records across partitions&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Message ordering for related events&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consumer workload distribution&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stateful stream processing&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stream joins and aggregations&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Overall cluster efficiency&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because the partition key affects both application correctness and cluster performance, it should be selected based on business requirements rather than convenience.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Semantic Keys vs Random Keys&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Partition keys generally fall into two categories.&amp;nbsp;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Semantic Keys&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Random Keys&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Customer ID&lt;/td&gt;
&lt;td&gt;UUID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vehicle ID&lt;/td&gt;
&lt;td&gt;Random String&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Device ID&lt;/td&gt;
&lt;td&gt;Auto-generated Identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Order ID&lt;/td&gt;
&lt;td&gt;Null Key (Round-Robin Distribution)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;When Should You Use Semantic Keys?&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Semantic keys represent a business entity whose events must remain in sequence.&lt;/p&gt;

&lt;p&gt;Examples include:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Customer ID&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vehicle ID&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Device ID&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Order ID&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Account ID&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if every telemetry event generated by &lt;strong&gt;Vehicle_1042&lt;/strong&gt; uses the vehicle ID as its partition key, all events for that vehicle are written to the same partition.&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Vehicle_1042&lt;/span&gt;&lt;span class="err"&gt;&amp;nbsp;&lt;/span&gt;
&lt;span class="err"&gt;&amp;nbsp;&lt;/span&gt;
  &lt;span class="nx"&gt;Engine&lt;/span&gt; &lt;span class="nx"&gt;Started&lt;/span&gt;&lt;span class="err"&gt;&amp;nbsp;&lt;/span&gt;
&lt;span class="err"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;   &lt;span class="err"&gt;↓&amp;nbsp;&lt;/span&gt;
  &lt;span class="nx"&gt;Location&lt;/span&gt; &lt;span class="nx"&gt;Updated&lt;/span&gt;&lt;span class="err"&gt;&amp;nbsp;&lt;/span&gt;
&lt;span class="err"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;   &lt;span class="err"&gt;↓&amp;nbsp;&lt;/span&gt;
  &lt;span class="nx"&gt;Speed&lt;/span&gt; &lt;span class="nx"&gt;Updated&lt;/span&gt;&lt;span class="err"&gt;&amp;nbsp;&lt;/span&gt;
&lt;span class="err"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;   &lt;span class="err"&gt;↓&amp;nbsp;&lt;/span&gt;
  &lt;span class="nx"&gt;Engine&lt;/span&gt; &lt;span class="nx"&gt;Stopped&lt;/span&gt;&lt;span class="err"&gt;&amp;nbsp;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because all events remain within a single partition, Kafka preserves their order throughout processing.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Semantic keys are recommended when applications require:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Ordered event processing&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stateful stream processing&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Event sourcing&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stream joins and aggregations&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Entity state management&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;When Should You Use Random or Null Keys?&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Not every workload requires message ordering.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;If records are independent and can be processed in any sequence, producers can use random keys or publish records without specifying a partition key. Kafka distributes these records across partitions, resulting in a more even workload distribution.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Random or null keys are commonly used for:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Log ingestion&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Metrics collection&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clickstream analytics&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Independent telemetry events&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;High-throughput event ingestion&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The trade-off is that events for the same entity may be written to different partitions, meaning Kafka no longer guarantees their relative order.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Designing an Effective Partition Key&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;A good partition key should:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Preserve ordering where required.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Have high cardinality to distribute traffic evenly.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remain stable throughout the application's lifecycle.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support future scaling without creating hotspots.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reflect the application's processing requirements rather than temporary business attributes.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Selecting fields such as &lt;strong&gt;Country&lt;/strong&gt;, &lt;strong&gt;Region&lt;/strong&gt;, &lt;strong&gt;Status&lt;/strong&gt;, or &lt;strong&gt;Event Type&lt;/strong&gt; often results in uneven traffic distribution because these values have relatively low cardinality. Business identifiers with many unique values typically provide a much better balance across partitions.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;How Condense Simplifies Partition Validation&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Choosing a partition key is only the first step. Validating that it distributes records as expected is equally important in production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Condense&lt;/strong&gt; simplifies this through &lt;strong&gt;Kafka Management&lt;/strong&gt;, allowing engineering teams to inspect messages at the partition level by selecting a specific partition, browsing records from any offset, viewing messages in JSON, Avro, or Protobuf formats, and publishing test messages directly to a chosen partition. These capabilities make it easier to verify partition key behavior, troubleshoot routing issues, and understand how records are distributed across Kafka topics without relying on external tooling.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practice:&lt;/strong&gt; Choose partition keys based on application behavior rather than convenience. High-cardinality business identifiers generally provide the best balance between message ordering, workload distribution, and long-term scalability. Validate the chosen strategy early using partition-level inspection before workloads reach production scale.&amp;nbsp;&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Do Poor Partition Keys Create Hotspots in Kafka Clusters?&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Even with the right number of partitions, a Kafka topic can still suffer from poor performance if records are distributed unevenly across those partitions. This typically happens when an ineffective partition key causes a disproportionate amount of traffic to be routed to a small number of partitions, creating &lt;strong&gt;hotspots&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;A hotspot occurs when one or more partitions receive significantly more records than others. Since each partition is processed independently, these overloaded partitions become bottlenecks, increasing consumer lag, producer latency, and broker resource utilization while other partitions remain underutilized.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;What Causes Partition Hotspots?&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Hotspots are usually caused by partition keys with &lt;strong&gt;low cardinality&lt;/strong&gt; or uneven business data distribution.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Consider an application that uses &lt;strong&gt;Country&lt;/strong&gt; as the partition key.&amp;nbsp;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Partition Key&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Percentage of Incoming Events&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;India&lt;/td&gt;
&lt;td&gt;82%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;United States&lt;/td&gt;
&lt;td&gt;8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Germany&lt;/td&gt;
&lt;td&gt;4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Other Countries&lt;/td&gt;
&lt;td&gt;6%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Although the topic may contain multiple partitions, most events associated with &lt;strong&gt;India&lt;/strong&gt; are consistently routed to the same partition. As traffic increases, that partition becomes overloaded while the remaining partitions process comparatively little data.&lt;/p&gt;

&lt;p&gt;This imbalance reduces the effectiveness of Kafka's parallel processing model.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Operational Impact of Hot Partitions&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Partition hotspots affect the entire streaming pipeline, not just a single consumer.&amp;nbsp;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;colgroup&gt;
&lt;col&gt;
&lt;col&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Component&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;&lt;strong&gt;Impact&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Producers&amp;nbsp;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Increased request latency and retries&amp;nbsp;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Consumers&amp;nbsp;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Higher consumer lag and slower event processing&amp;nbsp;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Brokers&amp;nbsp;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Uneven CPU, memory, disk, and network utilization&amp;nbsp;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Storage&amp;nbsp;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Faster growth of individual partitions&amp;nbsp;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Applications&amp;nbsp;&lt;/p&gt;&lt;/td&gt;
&lt;td colspan="1" rowspan="1"&gt;&lt;p&gt;Reduced throughput and inconsistent performance&amp;nbsp;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Over time, the busiest partition becomes the limiting factor for the application, regardless of the available capacity across the rest of the cluster.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Common Partition Key Mistakes&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;The following partition keys frequently lead to workload imbalance.&amp;nbsp;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Avoid Using&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Why It Creates Hotspots&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Better Alternative&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Country&lt;/td&gt;
&lt;td&gt;Uneven geographic traffic&lt;/td&gt;
&lt;td&gt;Customer ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Region&lt;/td&gt;
&lt;td&gt;Low cardinality&lt;/td&gt;
&lt;td&gt;Device ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Status&lt;/td&gt;
&lt;td&gt;Limited possible values&lt;/td&gt;
&lt;td&gt;Order ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Event Type&lt;/td&gt;
&lt;td&gt;Popular events dominate traffic&lt;/td&gt;
&lt;td&gt;Vehicle ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Boolean Fields&lt;/td&gt;
&lt;td&gt;Only two possible values&lt;/td&gt;
&lt;td&gt;Session ID&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The objective is to select partition keys with &lt;strong&gt;high cardinality&lt;/strong&gt;, allowing Kafka to distribute records more evenly across partitions while preserving ordering where required.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Detecting Hotspots Before They Become Production Issues&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Traffic patterns evolve over time. A partition key that distributes records evenly today may become imbalanced as specific customers, devices, or tenants generate significantly more events than others.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Engineering teams should continuously monitor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Consumer lag by partition&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Records processed per partition&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Partition assignment across consumers&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Broker CPU and memory utilization&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Partition storage growth&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consumer group health&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Monitoring these metrics helps identify workload imbalance before it impacts application performance.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;How Condense Simplifies Hotspot Detection&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Condense&lt;/strong&gt; provides partition-level visibility through its Kafka Management and observability capabilities, making it easier to identify workload imbalance as traffic patterns evolve. Engineering teams can monitor &lt;strong&gt;consumer lag for individual partitions&lt;/strong&gt;, track &lt;strong&gt;partition ownership and assignments across consumer groups&lt;/strong&gt;, view &lt;strong&gt;committed offsets and lag&lt;/strong&gt;, and monitor &lt;strong&gt;consumer group health&lt;/strong&gt;, including stable, rebalancing, and inactive states. These insights help teams detect hotspots early, validate whether workloads are evenly distributed, and determine when partition scaling or partition key changes may be required.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practice:&lt;/strong&gt; Designing an effective partition key is only part of the solution. Continuously monitor partition-level metrics to ensure workloads remain balanced as applications scale, and adjust partition strategy proactively before hotspots become production bottlenecks.&amp;nbsp;&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happens If You Have Too Few or Too Many Kafka Partitions?
&lt;/h2&gt;

&lt;p&gt;Choosing the right Kafka partition count is a balancing act. While partitions are the foundation of scalability and parallel processing, both under-partitioning and over-partitioning can introduce performance and operational challenges. The objective is not to maximize the number of partitions, but to provision enough partitions to support current workloads, accommodate future growth, and maintain efficient cluster operations.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;What Happens When There Are Too Few Partitions?&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Topics with too few partitions limit the amount of work that can be processed concurrently. Since each partition can be consumed by only one consumer within a consumer group, insufficient partitions restrict consumer parallelism regardless of how many consumer instances are deployed.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;As workloads grow, this often results in:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Limited consumer parallelism&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Higher consumer lag&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lower overall throughput&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Underutilized consumer instances&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reduced ability to scale horizontally&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if a topic has &lt;strong&gt;8 partitions&lt;/strong&gt; but an application requires &lt;strong&gt;20 consumers&lt;/strong&gt; to keep pace with incoming traffic, only &lt;strong&gt;8 consumers&lt;/strong&gt; can actively process records. The remaining &lt;strong&gt;12 consumers&lt;/strong&gt; remain idle because there are no partitions available to assign.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;What Happens When There Are Too Many Partitions?&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Although increasing partition count improves scalability, excessive partitioning introduces additional operational overhead. Every partition requires metadata management, broker resources, storage, and coordination during cluster operations.&lt;/p&gt;

&lt;p&gt;Creating significantly more partitions than required can lead to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Increased broker memory consumption&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;More metadata to manage&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Longer consumer group rebalancing&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Higher storage and file handle usage&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Slower broker startup and recovery&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Greater operational complexity&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These effects become increasingly noticeable in large production clusters hosting thousands of partitions across multiple brokers.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Comparing Both Approaches&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Design Consideration&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Too Few Partitions&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Too Many Partitions&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Consumer Parallelism&lt;/td&gt;
&lt;td&gt;Limits horizontal scaling&lt;/td&gt;
&lt;td&gt;Supports more consumers than required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Throughput&lt;/td&gt;
&lt;td&gt;Creates processing bottlenecks&lt;/td&gt;
&lt;td&gt;Additional partitions provide little benefit once throughput requirements are met&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Broker Resources&lt;/td&gt;
&lt;td&gt;Efficient metadata usage&lt;/td&gt;
&lt;td&gt;Higher memory and metadata overhead&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Consumer Rebalancing&lt;/td&gt;
&lt;td&gt;Faster&lt;/td&gt;
&lt;td&gt;Can take longer as partition count increases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Broker Recovery&lt;/td&gt;
&lt;td&gt;Faster&lt;/td&gt;
&lt;td&gt;Recovery and leader election involve more partitions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long-Term Scalability&lt;/td&gt;
&lt;td&gt;May require repartitioning sooner&lt;/td&gt;
&lt;td&gt;Better prepared for future growth, but with increased operational cost&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The ideal partition count balances these trade-offs while leaving sufficient headroom for expected growth.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Design for Growth, Not Just Current Workloads&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Many engineering teams size Kafka topics based only on current traffic, only to discover later that additional consumers cannot be utilized because the partition count has become the limiting factor.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;A more sustainable approach is to consider:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Expected peak throughput&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maximum consumer parallelism&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Business growth projections&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Seasonal traffic spikes&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Infrastructure capacity&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Planning with future growth in mind reduces the likelihood of repartitioning production topics as workloads evolve.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;How Condense Simplifies Partition Scaling&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;As streaming workloads increase, engineering teams often need to increase partition counts to maintain throughput and consumer parallelism. &lt;strong&gt;Condense&lt;/strong&gt; simplifies this process through &lt;strong&gt;Kafka Management&lt;/strong&gt;, allowing partition counts to be increased after topic creation while preserving the existing topic lifecycle. As data volumes grow, the platform helps engineering teams scale Kafka brokers and partitions together, enabling applications to handle higher event volumes without manual infrastructure coordination. This is particularly valuable for workloads with rapidly changing traffic patterns, such as connected vehicle platforms, IoT deployments, or event-driven applications that experience predictable peak events.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practice:&lt;/strong&gt; Select a partition count that supports both current and projected workloads rather than optimizing solely for today's traffic. As throughput and consumer demand increase, periodically review partition utilization and scale partitions proactively to maintain balanced workloads and consistent application performance.&amp;nbsp;&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Can You Safely Increase Kafka Partition Count Without Downtime?&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;As applications scale, increasing the number of Kafka partitions is often necessary to support higher throughput and greater consumer parallelism. Apache Kafka allows partition counts to be increased for existing topics without taking producers or consumers offline, making it possible to scale running applications with minimal disruption.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;However, increasing the partition count is more than a capacity upgrade. It changes how future records are distributed across partitions and can affect applications that depend on partition keys for ordering or stateful processing. Understanding these implications helps engineering teams scale topics safely while maintaining application correctness.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Can Kafka Increase and Decrease Partition Count?&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Kafka supports increasing the number of partitions for an existing topic, but it does not allow partitions to be removed.&amp;nbsp;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Operation&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Supported&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Notes&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Increase partition count&lt;/td&gt;
&lt;td&gt;✓ Yes&lt;/td&gt;
&lt;td&gt;Enables additional consumer parallelism and throughput&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decrease partition count&lt;/td&gt;
&lt;td&gt;✗ No&lt;/td&gt;
&lt;td&gt;Requires creating a new topic and migrating producers and consumers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Because partition counts cannot be reduced, capacity planning should consider future growth during the initial topic design.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;What Happens When You Increase the Partition Count?&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Kafka determines the destination partition for keyed records using the partition key and the total number of partitions.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Partition = hash(partition_key) % number_of_partitions&amp;nbsp;&lt;/p&gt;

&lt;p&gt;When the number of partitions changes, the calculated destination partition for future records may also change.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;For example:&amp;nbsp;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Before Scaling&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;After Scaling&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;8 Partitions&lt;/td&gt;
&lt;td&gt;16 Partitions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Customer_123 → Partition 3&lt;/td&gt;
&lt;td&gt;Customer_123 → Partition 11&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Existing records remain in their original partitions, while &lt;strong&gt;new records&lt;/strong&gt; are written according to the updated partition mapping.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;This distinction is important because Kafka &lt;strong&gt;does not redistribute existing records&lt;/strong&gt; when partitions are added.&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Should Engineering Teams Consider Before Scaling?&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Before increasing partition counts, evaluate whether your applications depend on:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Message ordering for a business entity&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stateful stream processing&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stream joins and aggregations&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consumer applications maintaining local state&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Historical event replay&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If ordering across the complete event history is a requirement, increasing partition count should be planned carefully.&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommended Migration Strategies&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;The safest approach depends on the application architecture.&amp;nbsp;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Strategy&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Recommended For&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Downtime&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Increase partitions in-place&lt;/td&gt;
&lt;td&gt;Stateless event processing&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Create a new topic with the desired partition count&lt;/td&gt;
&lt;td&gt;Stateful applications&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dual-write to both topics during migration&lt;/td&gt;
&lt;td&gt;Large production systems&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gradually migrate consumers&lt;/td&gt;
&lt;td&gt;Enterprise deployments&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Many engineering teams choose to create a new topic with the desired partition count for large production workloads. Producers publish to both topics during the migration period, consumers are validated against the new topic, and the original topic is retired once the migration is complete.&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Condense Simplifies Partition Scaling
&lt;/h2&gt;

&lt;p&gt;Scaling Kafka topics should not require engineering teams to manually coordinate infrastructure changes across multiple tools.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Using &lt;strong&gt;Kafka Management&lt;/strong&gt;, &lt;strong&gt;Condense&lt;/strong&gt; allows teams to increase partition counts as application workloads grow while continuing to manage the same Kafka topic throughout its lifecycle. As additional partitions are introduced, Condense provides visibility into &lt;strong&gt;consumer lag&lt;/strong&gt;, &lt;strong&gt;partition assignments&lt;/strong&gt;, &lt;strong&gt;committed offsets&lt;/strong&gt;, and &lt;strong&gt;consumer group health&lt;/strong&gt;, helping teams verify that workloads are being redistributed effectively.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;For consumer groups, Condense supports &lt;strong&gt;cooperative incremental rebalancing&lt;/strong&gt;, allowing Kafka to move only the affected partitions when consumers join or leave the group instead of reassigning every partition. This significantly reduces disruption, minimizes unnecessary data movement, and enables smoother scaling for production workloads.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Combined with broker scaling, partition management, and partition-level observability, engineering teams can expand streaming capacity while maintaining application stability during periods of sustained growth or peak traffic.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practice:&lt;/strong&gt; Plan partition growth before throughput becomes a bottleneck. Increase partitions based on measured workload trends, validate workload distribution using partition-level metrics, and use cooperative incremental rebalancing to minimize disruption during consumer scaling.&amp;nbsp;&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are the Most Common Kafka Partition Strategy Mistakes?&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Even experienced engineering teams can encounter partitioning issues as streaming workloads evolve. In many cases, performance bottlenecks are not caused by Kafka itself but by partitioning decisions made during the initial design phase. Understanding these common mistakes helps teams build Kafka deployments that remain scalable, balanced, and resilient as data volumes increase.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Choosing Partition Keys with Low Cardinality&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Partition keys such as &lt;strong&gt;Country&lt;/strong&gt;, &lt;strong&gt;Region&lt;/strong&gt;, &lt;strong&gt;Status&lt;/strong&gt;, or &lt;strong&gt;Event Type&lt;/strong&gt; have a limited number of unique values. As traffic grows, these values often create hotspots by routing a disproportionate amount of data to a small number of partitions.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Instead, choose high-cardinality identifiers such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Customer ID&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Device ID&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vehicle ID&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Order ID&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Session ID&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These keys distribute records more evenly while preserving ordering for related events.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Ignoring Future Consumer Parallelism&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Many teams size partition counts based only on their current deployment.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;For example:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Current deployment: &lt;strong&gt;4 consumers&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Topic configured with: &lt;strong&gt;4 partitions&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As the application grows, the team deploys &lt;strong&gt;12 consumers&lt;/strong&gt;, expecting throughput to increase. However, only four consumers actively process records because the partition count has become the limiting factor.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Always size partition counts based on expected peak consumer parallelism rather than today's deployment.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Prioritizing Throughput Over Ordering&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Using random or null partition keys can improve distribution across partitions, but it also removes ordering guarantees for related events.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Applications involving:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Financial transactions&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fleet telemetry&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inventory updates&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Customer state&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Event sourcing&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;typically require semantic partition keys to preserve event order.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Select the partition key based on application behavior rather than throughput alone.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Creating Excessive Partitions&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;More partitions do not automatically improve Kafka performance.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Excessive partition counts increase:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Broker metadata&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Memory usage&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;File handles&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consumer rebalancing time&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recovery time after failures&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Partition count should be determined through capacity planning and benchmarking instead of arbitrary sizing rules.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Not Monitoring Partition Health&lt;/strong&gt;&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Partition strategies should evolve as workloads change.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Traffic patterns that are evenly distributed today may become skewed as new customers, devices, or business regions generate significantly more events.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Engineering teams should continuously monitor:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Consumer lag&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Partition assignments&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Broker utilization&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Partition growth&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consumer group health&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These metrics provide early warning signs that partition counts or partition keys should be reviewed.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;Condense&lt;/strong&gt;, teams can monitor partition-level consumer lag, partition assignments, committed offsets, and consumer group health from a unified Kafka Management interface, making it easier to identify imbalance before it affects production workloads.&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  Treating Partition Strategy as a One-Time Activity&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Partition strategy should evolve alongside the application.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;As throughput, consumer groups, and traffic distribution change, engineering teams should periodically review:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Partition utilization&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consumer parallelism&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Workload distribution&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Broker capacity&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Future scaling requirements&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rather than waiting for consumer lag or hotspots to appear, proactively reviewing these metrics helps maintain consistent performance as streaming workloads grow.&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Mistakes at a Glance&amp;nbsp;
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Mistake&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Business Impact&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Recommended Approach&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Choosing low-cardinality partition keys&lt;/td&gt;
&lt;td&gt;Creates hotspots and uneven workloads&lt;/td&gt;
&lt;td&gt;Use high-cardinality business identifiers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sizing partitions only for current traffic&lt;/td&gt;
&lt;td&gt;Restricts future consumer scaling&lt;/td&gt;
&lt;td&gt;Plan for projected throughput and growth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ignoring ordering requirements&lt;/td&gt;
&lt;td&gt;Breaks event sequencing&lt;/td&gt;
&lt;td&gt;Use semantic partition keys where ordering matters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Creating excessive partitions&lt;/td&gt;
&lt;td&gt;Increases operational overhead&lt;/td&gt;
&lt;td&gt;Size partitions using throughput benchmarks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Not monitoring partition-level metrics&lt;/td&gt;
&lt;td&gt;Delays detection of workload imbalance&lt;/td&gt;
&lt;td&gt;Continuously monitor partition health and consumer lag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Treating partition strategy as static&lt;/td&gt;
&lt;td&gt;Limits long-term scalability&lt;/td&gt;
&lt;td&gt;Review and refine partition strategy as workloads evolve&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Best Practice:&lt;/strong&gt; Kafka partition strategy should be treated as an ongoing architectural practice rather than a one-time configuration task. Combining effective partition sizing, well-designed partition keys, continuous monitoring, and proactive capacity planning enables streaming applications to scale predictably while maintaining performance and reliability.&amp;nbsp;&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Kafka partition strategy is the foundation of every scalable Kafka deployment. It influences how data is distributed across brokers, determines the maximum level of consumer parallelism, preserves message ordering, and directly impacts throughput, resource utilization, and long-term cluster performance. Decisions made during topic design continue to influence application behavior long after workloads move into production, making partition strategy one of the most important architectural considerations in event streaming.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Designing an effective partition strategy requires balancing multiple factors. The right partition count should support expected throughput and future consumer parallelism without introducing unnecessary operational overhead. Partition keys should distribute workloads evenly while preserving ordering for events that belong together. As traffic patterns evolve, continuous monitoring helps identify hotspots, consumer lag, and partition imbalance before they affect application performance.&lt;/p&gt;

&lt;p&gt;While Apache Kafka provides the flexibility to configure and scale partitions, implementing and operating an effective partition strategy across production environments requires the right operational capabilities. &lt;strong&gt;Condense&lt;/strong&gt; simplifies the complete partition lifecycle through Kafka Management, enabling engineering teams to configure partitions during topic creation, scale partition counts as workloads grow, inspect partition-level data, monitor consumer lag and partition assignments, and manage consumer group rebalancing from a unified interface. This allows teams to focus on designing scalable streaming applications while simplifying the deployment, monitoring, and evolution of their Kafka infrastructure.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Whether you're building connected mobility platforms, IoT applications, real-time analytics pipelines, or event-driven microservices, investing time in the right Kafka partition strategy from day one helps build streaming systems that remain scalable, resilient, and easier to operate as data volumes continue to grow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions (FAQs)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What is a Kafka partition strategy?&lt;br&gt;&lt;br&gt;
A Kafka partition strategy defines how records are distributed across partitions within a topic. It involves selecting the appropriate partition count and partition key to balance workloads, maximize consumer parallelism, preserve message ordering where required, and support long-term scalability. A well-designed partition strategy improves throughput, reduces hotspots, and enables applications to scale efficiently&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How do I calculate the right Kafka partition count?&lt;br&gt;&lt;br&gt;
The partition count should be based on the larger of the producer throughput requirement and the consumer processing requirement. Factors such as message size, consumer processing complexity, replication factor, and future workload growth should also be considered. Rather than relying on fixed recommendations, benchmark representative workloads and size partitions for expected peak traffic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can I increase the number of Kafka partitions after creating a topic? Yes. Kafka allows partition counts to be increased after a topic is created, enabling additional consumer parallelism as workloads grow. However, increasing the partition count changes how future records are distributed because the partitioning algorithm uses the total number of partitions. Existing records remain in their original partitions. Using Condense, engineering teams can increase partition counts through Kafka Management while monitoring consumer lag, partition assignments, and consumer group health to validate that scaling has improved workload distribution&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How do I choose the right Kafka partition key?&lt;br&gt;&lt;br&gt;
Choose a partition key based on how the application processes data. If related events must remain in order, use a stable business identifier such as Customer ID, Device ID, Vehicle ID, or Order ID. If ordering is not required, random or null keys can distribute records more evenly across partitions and improve load balancing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What causes hotspots in Kafka partitions?&lt;br&gt;&lt;br&gt;
Hotspots occur when a small number of partitions receive significantly more traffic than others. This is commonly caused by partition keys with low cardinality or uneven business data distribution. Hotspots can increase consumer lag, overload brokers, and reduce overall throughput. Monitoring partition-level metrics helps identify these issues before they affect production workloads&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does adding more partitions always improve Kafka performance?&lt;br&gt;&lt;br&gt;
No. While additional partitions increase consumer parallelism and throughput capacity, they also increase broker metadata, memory usage, file handles, and consumer rebalancing overhead. The optimal partition count balances scalability with operational efficiency rather than simply maximizing the number of partitions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can Condense help manage Kafka partitions?&lt;br&gt;&lt;br&gt;
Yes. Condense simplifies Kafka partition management throughout the topic lifecycle. Engineering teams can configure partition counts during topic creation, increase partitions as workloads grow, inspect partition-level messages, monitor consumer lag and partition assignments, track consumer group health, and manage partition scaling from a unified Kafka Management interface. This helps teams implement and operate partition strategies more efficiently while continuing to leverage Apache Kafka&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What metrics should I monitor to validate my partition strategy?&lt;br&gt;&lt;br&gt;
A healthy partition strategy should be validated using operational metrics rather than assumptions. Engineering teams should regularly monitor:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Consumer lag by partition&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Partition throughput&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Partition assignments&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Broker CPU, memory, and storage utilization&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consumer group health&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Partition growth over time&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Monitoring these metrics helps identify hotspots, workload imbalance, and scaling requirements before they impact application performance&lt;/p&gt;

</description>
      <category>kafka</category>
      <category>condense</category>
      <category>eventdriven</category>
      <category>kafkaguide</category>
    </item>
    <item>
      <title>Why Your Kafka Stack Is Holding You Back (And How to Fix It)</title>
      <dc:creator>Sachin Kamath</dc:creator>
      <pubDate>Sat, 18 Jul 2026 13:14:23 +0000</pubDate>
      <link>https://dev.to/zeliotofficial/why-your-kafka-stack-is-holding-you-back-and-how-to-fix-it-1gh4</link>
      <guid>https://dev.to/zeliotofficial/why-your-kafka-stack-is-holding-you-back-and-how-to-fix-it-1gh4</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Apache Kafka remains foundational but managing it alone is complex and inadequate for modern real-time needs.&lt;/p&gt;

&lt;p&gt;Condense modernizes Kafka by providing a fully managed, Kafka-native streaming platform deployed inside your cloud (BYOC) with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Prebuilt, domain-specific transforms&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Low-code, Git-integrated IDE for stream logic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cloud-native autoscaling and zero-downtime upgrades&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Full observability and lifecycle management&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data sovereignty and cost control via BYOC&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Leading enterprises use Condense to build scalable, domain-aware, production-ready real-time applications quickly and reliably, moving beyond raw Kafka infrastructure to real business outcomes.&lt;/p&gt;

&lt;p&gt;Apache Kafka has remained the backbone of event-driven architectures for over a decade. Its immutable log abstraction, scalable broker design, and stream-first philosophy have powered countless real-time systems, from fraud detection and e-commerce analytics to telematics ingestion and industrial automation.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;But the world around Kafka has evolved. Data volumes have exploded. Cloud economics have shifted. Developer expectations have changed. And most critically, the business demands from real-time systems have moved far beyond what an isolated Kafka cluster can provide.&amp;nbsp;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In 2025, continuing to operate Kafka as it was done a few years ago like manually managed, loosely integrated, and layered with custom scripts is increasingly unsustainable. Here are five deeply technical and operational reasons why modernizing the Kafka stack is no longer optional, but strategic.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Reason 1: Kafka Alone Isn’t a Platform&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Running Kafka by itself delivers transport but not outcomes. Most real-time use cases depend on an entire ecosystem of critical components around Kafka, including:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Schema registries&lt;/strong&gt; for versioned serialization&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stream processors&lt;/strong&gt; for business logic execution&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Connectors&lt;/strong&gt; for integration with databases, filesystems, APIs, or telemetry streams&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monitoring agents&lt;/strong&gt; to observe lag, consumer health, and throughput bottlenecks&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security layers&lt;/strong&gt; for multi-tenant isolation, role-based access, and encryption&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When these components are stitched together manually, organizations inherit the burden of lifecycle management: upgrades, patching, configuration drift, dependency mismatches, downtime orchestration, and incident response.&amp;nbsp;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Modernizing the Kafka stack means adopting a &lt;strong&gt;cohesive, cloud-native runtime&lt;/strong&gt; where these components work in unison, ideally under a single operational contract. This creates a predictable, observable, and sustainable foundation for stream-first workloads.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Reason 2: Developer Velocity Demands Better Abstractions&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;The Kafka ecosystem has traditionally favored infrastructure engineers and backend specialists. Defining stream joins, windowing logic, or repartitioning flows requires deep knowledge of Kafka Streams, KSQL, or Flink plus careful handling of topic schemas, backpressure, and message formats.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;As event-driven logic becomes part of core business applications, whether it’s scoring driver behavior, flagging transaction anomalies, or transforming IoT telemetry, developer experience becomes a bottleneck.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Modern stacks must support:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Low-code interfaces&lt;/strong&gt; for operational workflows&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GitOps workflows&lt;/strong&gt; for versioned stream deployments&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AI-assisted IDEs&lt;/strong&gt; to auto-generate transformation templates&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Live testing environments&lt;/strong&gt; that simulate events before production rollout&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Without these capabilities, real-time use cases become slower to deliver and harder to iterate, putting Kafka-centric architectures at odds with agile product cycles.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Reason 3: Cloud-Native Architecture Is Now Table Stakes&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Migrating to a cloud-aligned architecture reduces operational complexity, increases utilization efficiency, and enables faster scale-out for peak workloads, without human intervention.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;In 2025, most Kafka workloads run on cloud infrastructure, whether in VMs, managed Kubernetes clusters, or fully serverless runtimes. Yet traditional Kafka deployments often ignore cloud-native principles:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Manual node provisioning leads to overprovisioning or underperformance.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No support for autoscaling brokers or connectors based on demand.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lack of integration with cloud IAM, logging, and billing complicates security and cost attribution.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Self-managed high availability adds operational tax for each region or zone.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Modern platforms treat Kafka as one component in a broader &lt;strong&gt;elastic data plane&lt;/strong&gt;. Brokers auto-scale. Connectors spin up based on load. Stream processors run in serverless containers. Failovers are orchestrated automatically. Monitoring is pushed into existing cloud-native observability stacks.&amp;nbsp;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Migrating to a cloud-aligned architecture reduces operational complexity, increases utilization efficiency, and enables faster scale-out for peak workloads, without human intervention.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Reason 4: Real-Time Use Cases Now Depend on Domain-Aware Processing&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Kafka is a generic tool. But most real-time applications are &lt;strong&gt;domain-specific&lt;/strong&gt;. Consider:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In &lt;strong&gt;mobility&lt;/strong&gt;, real-time logic might involve VIN-based trip formation, geofence entry/exit events, and harsh braking classification.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;strong&gt;logistics&lt;/strong&gt;, it may involve cargo temperature violation alerts, trip ETA updates, and route compliance tracking.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;strong&gt;finance&lt;/strong&gt;, real-time use cases often involve transaction scoring, KYC triggers, or payment retry orchestration.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These patterns cannot be implemented through raw Kafka APIs or SQL-like interfaces. They demand &lt;strong&gt;prebuilt, domain-native transforms&lt;/strong&gt; that understand context. e.g., how to interpret an OBD-II message, what constitutes a loading zone, or how to calculate SLA breach probability in transit.&amp;nbsp;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Modern Kafka platforms incorporate &lt;strong&gt;verticalized logic libraries&lt;/strong&gt;, deployable out-of-the-box, saving engineering months of effort while improving accuracy and operational trust.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Reason 5: Cost Optimization and BYOC Are Now Strategic Priorities&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;As enterprise cloud bills grow, organizations are rethinking the economics of managed Kafka. Traditional hosted platforms run Kafka inside the vendor’s cloud account, which leads to:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Double billing (vendor cost + unused cloud credits)&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lack of visibility into runtime costs&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inability to apply reserved instances or volume discounts&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No control over data egress patterns or compliance enforcement&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Modern Kafka platforms support Bring Your Own Cloud (BYOC) where all infrastructure runs in the enterprise’s cloud account, using its cloud credits and governance tools. This offers:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Full cost control and transparency&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Better alignment with existing cloud agreements&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data sovereignty and compliance retention&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Direct integration with internal monitoring, alerting, and IAM systems&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;BYOC is not just about infrastructure flexibility; now it is a financial, legal, and strategic enabler for Kafka adoption at scale.&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  Kafka Needs a Platform, Not Just Brokers&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;The technical power of Kafka is undiminished. But its role has changed. Kafka is no longer the end goal. It’s the foundation upon which real-time business logic, domain-aware intelligence, and operational outcomes are built.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Modernizing the Kafka stack means wrapping it with the necessary abstractions, integrations, and delivery systems required to thrive in production. The shift is from Modernizing the Kafka stack means wrapping it with the necessary abstractions, integrations, and delivery systems required to thrive in production. The shift is from &lt;strong&gt;running brokers&lt;/strong&gt; to &lt;strong&gt;delivering applications&lt;/strong&gt;. From managing infrastructure to enabling decisions in motion.&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Condense?&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Condense is built for this new era of real-time streaming. It is a Kafka-native platform, delivered via BYOC, and tailored to industries like mobility, logistics, industrial automation, and connected infrastructure.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;With prebuilt transforms, low-code development, AI-assisted IDEs, and full cloud integration, Condense reduces time-to-value while increasing platform trust. It brings together Kafka, stream logic, deployment tooling, and observability, without requiring a dedicated SRE team to keep things running.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;In 2025, Kafka alone is no longer enough. The future belongs to streaming platforms that don’t just deliver logs, but understand the domain behind every message. Systems where VINs aren’t just strings, but identifiers for operational context. Where a harsh brake isn't just a sensor value, but a signal that may affect safety, routing, or warranty.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Condense leads that transformation. It extends Kafka with domain semantics, real-time transforms pre-aligned with industry workflows, and infrastructure that runs inside the enterprise’s own cloud environment. Kafka becomes more than transport; it becomes the foundation for intelligent, outcome-driven applications that speak the language of the domain.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;That’s why enterprises like Volvo, Eicher, Royal Enfield, Michelin, CEAT and TVS have moved beyond generic Kafka clusters and toward streaming platforms like Condense, where real-time pipelines are not just technically correct, but operationally meaningful.&amp;nbsp;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Each of these industries requires different connectors, semantic models, latency expectations, and deployment constraints. Condense abstracts that complexity through domain-aligned transforms, BYOC infrastructure, and a Kafka-native architecture, so organizations don’t just stream data, but operationalize it.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions (FAQs)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Is Apache Kafka being replaced?&lt;br&gt;&lt;br&gt;
No. Apache Kafka remains a foundational component for event streaming. What's changing is the ecosystem around it. Modern organizations are moving away from raw Kafka clusters and toward integrated platforms that combine Kafka with stream processing, domain logic, observability, security, and deployment automation. The goal is not to replace Kafka, but to make it production-grade and outcome-oriented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What does it mean to "modernize" a Kafka stack?&lt;br&gt;&lt;br&gt;
Modernization involves evolving from a loosely assembled set of Kafka services to a platform where stream processing is:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Domain-aligned (industry-specific logic and semantics)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cloud-native (autoscaling, managed failover, integrated monitoring)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Developer-ready (GitOps, low-code, AI-assisted transforms)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cost-efficient (BYOC, cloud credit utilization)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's about increasing delivery speed and reducing operational burden, without losing Kafka's core strengths.&lt;/p&gt;

&lt;p&gt;3. Why is developer velocity relevant to Kafka architecture?&lt;br&gt;&lt;br&gt;
Kafka was historically managed by infrastructure teams. But today, product and application teams are building on top of Kafka for use cases like real-time pricing, routing intelligence, maintenance prediction, and alerting. If the underlying stack requires custom JVM code or complex DSLs for every transformation, delivery slows down.&lt;/p&gt;

&lt;p&gt;Modern platforms provide abstractions that let domain experts and developers collaborate at speed, without needing to be Kafka internals experts.&lt;/p&gt;

&lt;p&gt;4. What is the role of domain awareness in Kafka-based systems?&lt;br&gt;&lt;br&gt;
Raw Kafka doesn't know the difference between a vehicle ID and a sensor type. But real-time systems increasingly depend on contextual interpretation: route IDs, fleet zones, compliance flags, shipment IDs, etc. Domain-aware platforms bring this intelligence closer to the data plane, embedding semantic understanding into transforms, alerting, and visualization. This eliminates the need to re-encode business logic downstream in BI tools or service code.&lt;/p&gt;

&lt;p&gt;5. What is BYOC, and why does it matter for Kafka?&lt;br&gt;&lt;br&gt;
BYOC (Bring Your Own Cloud) allows the Kafka platform and supporting services to run fully inside the enterprise's own cloud account (AWS, Azure, GCP). The platform is still vendor-operated but leverages the customer's cloud credits, IAM policies, observability stack, and compliance posture.&lt;/p&gt;

&lt;p&gt;This ensures data sovereignty, cost efficiency, and deep integration, without requiring the enterprise to self-manage Kafka infrastructure.&lt;/p&gt;

&lt;p&gt;6. How does Condense modernize Kafka differently?&lt;br&gt;&lt;br&gt;
Condense builds on Kafka's architecture but adds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Prebuilt, domain-specific transforms (e.g., for mobility, logistics, energy)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A low-code/IDE interface for defining and deploying stream logic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CI/CD pipelines for stream application lifecycle management&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Native BYOC deployment support across AWS, Azure, and GCP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Isolation by default, with full auditability and customer-bounded operations&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It enables streaming-native applications to be built and deployed in days, not quarters, without requiring deep Kafka expertise or large ops teams.&lt;/p&gt;

&lt;p&gt;7. What kinds of organizations are using Condense?&lt;br&gt;&lt;br&gt;
Condense is trusted by a broad spectrum of enterprises and system integrators operating in data-intensive, real-time environments. These span across:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Automotive OEMs including Volvo, Royal Enfield, and TVS Motor, using Condense for OTA updates, remote diagnostics, vehicle analytics, and feature lifecycle control&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fleet and Mobility Platforms such as Eicher, SML Isuzu, and Taabi Mobility, relying on Condense for trip intelligence, predictive maintenance, panic alerting, and live telematics processing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Logistics and Transportation Networks including Michelin and various freight, mining, and container mobility platforms using Condense for multi-modal tracking, cold chain eventing, and geofenced security&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Industrial and Manufacturing Operations streaming real-time production telemetry, detecting bottlenecks, balancing workloads, and ensuring operational continuity using data from PLCs and SCADA systems&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Financial Services where Condense enables fraud detection pipelines, transaction anomaly flagging, and secure, compliant integration with downstream rule engines and audit layers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Smart Cities and Public Infrastructure powering streaming use cases in traffic signal networks, emergency response coordination, and public transportation tracking with millisecond latency&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Travel and Hospitality Systems: Unifying data from property management systems (PMS), shuttle tracking, booking engines, and mobile apps to enable dynamic rate optimization, real-time availability, and multilingual customer notifications&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Condense allows hotel chains, airport service providers, and hospitality tech platforms to detect and react to changes, such as flight delays, booking conflicts, or room state transitions, in real time.&lt;/p&gt;

</description>
      <category>kafka</category>
      <category>data</category>
      <category>streamingdata</category>
      <category>dataplaform</category>
    </item>
    <item>
      <title>What Is Apache Kafka? Plain-English Guide for Engineers (2026)</title>
      <dc:creator>Sachin Kamath</dc:creator>
      <pubDate>Wed, 15 Jul 2026 06:15:59 +0000</pubDate>
      <link>https://dev.to/zeliotofficial/what-is-apache-kafka-plain-english-guide-for-engineers-2026-2oe4</link>
      <guid>https://dev.to/zeliotofficial/what-is-apache-kafka-plain-english-guide-for-engineers-2026-2oe4</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Apache Kafka is a high-throughput, fault-tolerant distributed event streaming platform ideal for real-time data processing. It organizes data into replicated topics and partitions, ensuring scalability and reliability. Kafka uses a pull-based consumer model and supports hybrid messaging (pub/sub and queuing). It offers flexible data retention, security features, and APIs for stream processing and integrations.&lt;/p&gt;

&lt;p&gt;Condense builds on Kafka by providing fully managed, scalable, and cost-optimized Kafka deployments with industry-specific intelligence and verticalized data pipelines. It removes operational complexity and accelerates real-time insights for enterprises, enabling easier adoption and faster value delivery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction&amp;nbsp;to Apache Kafka
&lt;/h2&gt;

&lt;p&gt;Apache Kafka is an open-source distributed event streaming platform developed by the Apache Software Foundation. It is designed to handle high-throughput, fault-tolerant, durable, and scalable real-time data feeds. Kafka is widely used in real-time data pipelines, event-driven architectures, and Kafka Streams libraries for stream processing applications.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Originally developed at LinkedIn in 2010 to address growing data processing needs, Kafka was open-sourced in 2011 and has since become an integral part of modern data architectures.&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;
  
  
  Kafka as a Distributed System&amp;nbsp;
&lt;/h3&gt;

&lt;p&gt;Kafka operates as a distributed system, meaning data is stored and processed across multiple machines to ensure high availability and fault tolerance. This architecture allows Kafka to handle millions of messages per second, making it ideal for large-scale, real-time applications.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Kafka is horizontally scalable, allowing organizations to add more servers (brokers) as demand increases. Unlike traditional messaging systems, Kafka employs log-based storage, where data is written sequentially, reducing disk I/O bottlenecks and improving performance.&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;
  
  
  Kafka as an Event Streaming Platform&amp;nbsp;
&lt;/h3&gt;

&lt;p&gt;Kafka is more than just a messaging system; it enables applications to capture, process, and react to real-time data changes. This capability is valuable for:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Real-time monitoring (e.g., log analysis, security alerts).&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Streaming analytics (e.g., fraud detection, stock trading, IoT analytics).&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Decoupling microservices (i.e., enabling efficient service-to-service communication via event streams).&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kafka integrates seamlessly with cloud-native environments, including Kubernetes, containerized applications, and managed cloud services.&amp;nbsp;Managing data schemas across producers and consumers is one of the most critical operational challenges teams face.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kafka’s Core Concepts&amp;nbsp;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Topics, Partitions, and Offsets&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Kafka organizes data into:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Topics: Logical channels for message streams.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Partitions: Subdivisions of topics that distribute data across brokers.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Offsets: Unique identifiers assigned to each message within a partition, ensuring ordered message sequences.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each partition is replicated across brokers for fault tolerance. If a broker fails, Kafka automatically redirects traffic to another broker with a replica.&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;
  
  
  Kafka’s High Availability &amp;amp; Fault Tolerance&amp;nbsp;
&lt;/h3&gt;

&lt;p&gt;Kafka achieves reliability through leader-follower replication:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Each partition has a leader handling read/write requests.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Follower replicas synchronize with the leader and take over in case of failure.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This ensures continuous data availability and prevents data loss.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Kafka’s Pull-Based Consumer Model&amp;nbsp;
&lt;/h3&gt;

&lt;p&gt;Unlike traditional push-based messaging systems, Kafka follows a pull-based model, where consumers retrieve messages at their own pace. Benefits include:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Backpressure handling: Prevents overwhelming consumers with excessive data.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flexible message processing: Consumers can reprocess messages by adjusting offsets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Efficient batching: Consumers can read multiple messages at once for better performance.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Kafka’s Internal Architecture&amp;nbsp;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Zookeeper’s Role in Kafka&amp;nbsp;
&lt;/h4&gt;

&lt;p&gt;Kafka uses Apache Zookeeper for:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Leader election and failover handling.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configuration management.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tracking broker metadata.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Kafka 4.0.0 Update: The removal of ZooKeeper in Kafka 4.0 simplified this architecture significantly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Producer
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Partitioning Strategy: Messages are distributed across partitions based on a key or a round-robin method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Batching &amp;amp; Compression: Kafka supports gzip, Snappy, and LZ4 to optimize data transmission.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Acknowledgment Levels:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  acks=0 → No acknowledgment (fastest but risky).&amp;nbsp;&lt;/li&gt;
&lt;li&gt;  acks=1 → Acknowledged by leader only (some risk).&amp;nbsp;&lt;/li&gt;
&lt;li&gt;  acks=all → Acknowledged by leader and all in-sync replicas (safest).&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Consumer&amp;nbsp;&amp;nbsp;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Consumer Groups: Consumers are grouped to distribute workload efficiently.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Offset Management: Kafka tracks processed messages using internal consumer_offsets topics.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dynamic Rebalancing: If a consumer joins or leaves, Kafka dynamically redistributes partitions.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Kafka’s Pub-Sub and Message Queuing Hybrid Model&amp;nbsp;
&lt;/h3&gt;

&lt;p&gt;Kafka blends publish-subscribe (pub-sub) and message queuing models:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Message Queuing: Each consumer reads different messages, ensuring parallel processing.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publish-Subscribe: Multiple consumers can read from the same topic, allowing multiple applications to process the same data stream in real-time.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Kafka’s Retention, Deletion, and Compaction
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Time-based Retention: Messages persist for a defined period (default: 7 days).&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Size-based Retention: Kafka deletes older messages if the topic exceeds a configured size.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Log Compaction: Instead of deleting messages, Kafka retains only the latest version of a message per key.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Kafka’s Replication Mechanism
&lt;/h3&gt;

&lt;p&gt;Kafka follows a leader-follower model with In-Sync Replicas (ISR)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ISR contains follower replicas that are synchronized with the leader.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unclean Leader Election: If all ISR replicas fail, Kafka can elect an out-of-sync replica unless explicitly disabled (unclean.leader.election.enable=false).&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Kafka Security Mechanisms
&lt;/h3&gt;

&lt;p&gt;Kafka offers multiple security features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Authentication: Supports SASL, Kerberos, and SSL-based authentication.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Authorization: Role-based access control (RBAC) using Kafka ACLs.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data Encryption: SSL/TLS for data in transit, cloud-based encryption for data at rest.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Kafka’s Stream Processing &amp;amp; APIs&amp;nbsp;
&lt;/h3&gt;

&lt;p&gt;Kafka offers several APIs for real-time data processing:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Kafka Streams API: Transforms, aggregates, and enriches data streams (e.g., real-time fraud detection).&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;KSQL (Kafka SQL): Enables SQL-like querying on Kafka topics (e.g., filtering IoT sensor data in real-time).&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Kafka Connect API: Integrates Kafka with external databases and cloud storage (e.g., syncing Kafka with a cloud data warehouse).&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kafka Performance Optimization&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Increase Partition Count: More partitions allow parallelism but increase metadata overhead.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Broker Tuning:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  log.segment.bytes: Defines segment size before Kafka rolls to a new log file.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;  log.retention.hours: Configures data retention duration.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;  num.network.threads: Handles network request concurrency.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Producer &amp;amp; Consumer Tuning:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  batch.size: Controls message batching.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;  linger.ms: Introduces delays to improve batching.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;  fetch.min.bytes: Determines the minimum amount of data consumers request per fetch.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Kafka in Multi-Datacenter &amp;amp; Cross-Region Setups&amp;nbsp;
&lt;/h3&gt;

&lt;p&gt;Kafka supports cross-region replication using MirrorMaker, ensuring:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Disaster recovery.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Regulatory compliance.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Efficient geographically distributed workloads.&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apache Kafka is a scalable, fault-tolerant event streaming platform that enables real-time data processing, analytics, and microservices communication. With its log-based storage, pub-sub hybrid model, high availability, and security features, Kafka remains a key component of modern cloud-native architectures.&amp;nbsp;With the Kafka 4.0 update, the architecture has shifted significantly. ZooKeeper is gone, replaced by KRaft.&lt;/p&gt;

&lt;h2&gt;
  
  
  Condense: A Vertical Data Streaming Platform&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;While Kafka is powerful, managing it requires expertise and operational effort. Security configurations, including mTLS, SASL, and ACLs is one of the most complex operational requirements. Condense builds upon Kafka, offering a fully managed streaming platform with an optimized, industry-specific verticalized ecosystem.&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  Key Benefits of Condense&amp;nbsp;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Fully Managed BYOC (Bring Your Own Cloud): Ensures data sovereignty by deploying within the customer’s cloud environment, removing infrastructure management burdens.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fully Managed Kafka with 99.95% Availability: Eliminates downtime risks and ensures uninterrupted data streaming.&amp;nbsp;Monitoring consumer lag, broker health, and pipeline throughput is critical for maintaining that availability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Autonomous Scalability: Automatically adjusts resources based on demand.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enterprise Support and Zero-Touch Management: 24/7 support, removing operational complexity.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verticalized Cloud Cost Optimization: Reduces cloud expenses while maintaining performance. Condense brings in the domain expertise to govern the optimal utilization of the resources.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No Latency Issues, Regardless of Throughput: Guarantees ultra-low latency even under extreme data loads.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Choose Condense Over Self-Managed Kafka?&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Managing Kafka in-house requires extensive DevOps resources, monitoring, and scaling expertise. Condense eliminates these challenges, allowing businesses to leverage Kafka’s full potential without the complexity.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Kafka has revolutionized real-time data streaming, but Condense takes it further, providing a fully managed, highly available, and cost-optimized platform. With zero-latency issues, automated scaling, and enterprise-grade support, Condense ensures seamless data streaming for modern businesses.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Apache Kafka and Condense together empower organizations with scalable, fault-tolerant event streaming capabilities.&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions (FAQs)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What is Apache Kafka?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Apache Kafka is an open-source distributed event streaming platform originally built at LinkedIn in 2010 and open-sourced in 2011. It's designed for high-throughput, fault-tolerant, real-time data feeds and is widely used in data pipelines, event-driven architectures, and stream processing applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What is Kafka used for?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Kafka powers real-time monitoring (log analysis, security alerts), streaming analytics (fraud detection, IoT analytics, stock trading), and microservices decoupling, where services communicate via event streams instead of direct calls. It integrates natively with Kubernetes, containers, and managed cloud services.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How does Kafka work?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Kafka organizes data into topics, which are split into partitions distributed across brokers. Each message in a partition gets a unique offset, ensuring ordered sequences. Partitions are replicated across brokers using a leader-follower model, so if a broker fails, a synchronized replica takes over automatically with no data loss.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Is Kafka a message queue or a pub-sub system?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Both. Kafka is a hybrid. Within a consumer group, each consumer reads different messages (queuing, for parallel processing), while multiple consumer groups can independently read the same topic (pub-sub, so several applications can process the same stream in real time).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What is the difference between Kafka and traditional messaging systems?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Two big ones: Kafka uses log-based storage where data is written sequentially, reducing disk I/O bottlenecks, and it uses a pull-based consumer model where consumers fetch messages at their own pace. This enables backpressure handling, message reprocessing by adjusting offsets, and efficient batching.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Does Kafka still need ZooKeeper?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
No. As of Kafka 4.0, ZooKeeper has been removed entirely and replaced by KRaft, which simplifies the architecture. Previously, ZooKeeper handled leader election, configuration management, and broker metadata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How long does Kafka retain data?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
By default, 7 days (time-based retention). You can also configure size-based retention, where older messages are deleted once a topic exceeds a set size, or log compaction, which keeps only the latest version of each message per key.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Is Kafka secure?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Kafka supports SASL, Kerberos, and SSL-based authentication, role-based access control via ACLs, and SSL/TLS encryption in transit. That said, configuring mTLS, SASL, and ACLs correctly is one of the most complex operational requirements teams face when self-managing Kafka.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How do you scale Kafka?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Kafka scales horizontally by adding brokers, and parallelism increases with partition count (though more partitions add metadata overhead). Performance tuning also involves broker settings (segment size, retention, network threads) and producer/consumer settings like batch size, linger time, and fetch minimums.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What is Condense and how does it relate to Kafka?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
 Condense is a fully managed data streaming platform built on Kafka. It removes the operational burden of running Kafka: security configuration, scaling, monitoring, and DevOps expertise, while adding an industry-verticalized ecosystem on top.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What does BYOC mean in Condense?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
 Bring Your Own Cloud: Condense deploys entirely within your own cloud environment, so your data never leaves your account and you retain full data sovereignty, while Condense manages the infrastructure end-to-end.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Why choose Condense over self-managed Kafka?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
 Self-managing Kafka demands extensive DevOps resources for monitoring consumer lag, broker health, and pipeline throughput, plus deep scaling and security expertise. Condense delivers 99.95% availability, autonomous scaling, ultra-low latency at any throughput, and 24/7 enterprise support without a dedicated platform team.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>kafka</category>
      <category>eventdriven</category>
      <category>dataengineering</category>
      <category>datastreaming</category>
    </item>
    <item>
      <title>Privatise your Data Streams with Bring Your Own Cloud (BYOC)</title>
      <dc:creator>Sachin Kamath</dc:creator>
      <pubDate>Tue, 14 Jul 2026 03:25:10 +0000</pubDate>
      <link>https://dev.to/zeliotofficial/privatise-your-data-streams-with-bring-your-own-cloud-byoc-4f8d</link>
      <guid>https://dev.to/zeliotofficial/privatise-your-data-streams-with-bring-your-own-cloud-byoc-4f8d</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Traditional SaaS streaming requires exporting sensitive data to a vendor cloud, creating security risks and egress costs. BYOC reverses this model by running the data plane inside the customer’s cloud while the vendor manages the control plane. This keeps data within the enterprise perimeter while still providing a managed platform. Condense builds on this model with AI-driven automation, unified monitoring, and marketplace deployment, enabling private, compliant, and cost-efficient real-time data streaming.&lt;/p&gt;

&lt;p&gt;The enterprise data landscape is currently defined by a conflict between real-time &lt;strong&gt;AI data streaming&lt;/strong&gt; utility and the strict requirements of &lt;strong&gt;data sovereignty&lt;/strong&gt;. For years, the standard SaaS model forced a compromise. To access premium analytics, companies had to export sensitive telemetry to a vendor cloud. This created massive &lt;strong&gt;cloud egress costs&lt;/strong&gt; and introduced significant security vulnerabilities.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bring Your Own Cloud (BYOC)&lt;/strong&gt; for &lt;strong&gt;data streaming platforms&lt;/strong&gt; has emerged as the professional solution to this dilemma. It allows a business to keep data within its own perimeter while benefiting from a fully managed, high-performance ecosystem.&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  The BYOC Architecture: Privacy by Design&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;An experienced analyst views BYOC as a clean separation of concerns. The architecture splits the environment into two distinct layers to ensure raw data never leaves the authorized environment.&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SaaS Control Plane:&lt;/strong&gt; This is the management layer hosted by the provider. It handles the brain of the operation. It manages orchestration, user access, and pipeline configuration without ever seeing the actual data packets.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Private Data Plane:&lt;/strong&gt; This is the muscle. The &lt;strong&gt;managed Kafka clusters&lt;/strong&gt;, &lt;strong&gt;Kubernetes (K8s)&lt;/strong&gt; nodes, and storage engines like ClickHouse live inside the customer &lt;strong&gt;Virtual Private Cloud (VPC)&lt;/strong&gt;.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;By keeping the data plane inside the customer perimeter, &lt;strong&gt;telemetry collection&lt;/strong&gt; remains private. This architecture is the most direct path to satisfying internal security audits and global regulatory bodies.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Economic Advantage of Cloud Marketplace Integration&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;The move to BYOC is a financial strategy as much as a technical one. When a platform like &lt;strong&gt;Condense&lt;/strong&gt; is deployed through a &lt;strong&gt;Cloud Marketplace&lt;/strong&gt; such as AWS, Azure, or GCP, it unlocks three major economic levers.&amp;nbsp;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Commitment Drawdown:&lt;/strong&gt; Most large enterprises have pre-existing spending commitments with cloud providers. Purchasing through the marketplace allows these software costs to count toward those totals. It turns a budget into high-value infrastructure.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ending the Data Tax:&lt;/strong&gt; One of the primary killers of ROI in data projects is the egress fee. By co-locating the streaming producers and consumers in the same region, the tax for moving data to an external SaaS cloud is eliminated.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Procurement Speed:&lt;/strong&gt; Consolidating costs into a single cloud provider invoice bypasses months of vendor onboarding and complex billing cycles.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Intelligence and Automation via AI Agents&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;A privatised data stream is only useful if it is manageable. The &lt;strong&gt;Condense&lt;/strong&gt; platform provides a unified ecosystem that goes beyond simple hosting. It includes specialized &lt;strong&gt;AI Agents&lt;/strong&gt; designed to handle the heavy lifting of distributed systems.&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Infrastructure and K8s Agents:&lt;/strong&gt; These handle the automated management of Kafka brokers and Kubernetes clusters. They ensure high availability without needing a massive internal DevOps team.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pipeline and Code Assistants:&lt;/strong&gt; These agents help R&amp;amp;D teams build &lt;strong&gt;data pipelines&lt;/strong&gt; and custom code frameworks much faster than manual coding.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Native Monitoring:&lt;/strong&gt; Instead of jumping between multiple tools, everything from ingestion to transformation is visible in one managed interface.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sovereignty and the DPDP Act in India&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;For businesses operating under the &lt;strong&gt;DPDP Act in India&lt;/strong&gt;, the BYOC model is a primary compliance tool. It provides the technical evidence required to prove that sensitive information is handled correctly.&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Residency:&lt;/strong&gt; Physical storage stays within the country. This prevents unauthorized cross-border data movement.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Advanced Key Management:&lt;/strong&gt; Support for &lt;strong&gt;Customer-Managed Keys (CMK)&lt;/strong&gt; and BYOK ensures that even the cloud provider cannot decrypt the data.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Confidential Computing:&lt;/strong&gt; For the most sensitive workloads, data remains encrypted even while it is being processed in memory.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Strategic Recommendations&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;To get the most out of a &lt;strong&gt;private data stream&lt;/strong&gt;, focus on these three pillars.&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Respect Data Gravity:&lt;/strong&gt; Place workloads where the data already lives to reduce latency and architectural complexity.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build Clean Paths:&lt;/strong&gt; For &lt;strong&gt;real-time AI inference&lt;/strong&gt;, use private metro connectivity and deterministic routing. This guarantees the low latency needed for agentic workloads.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security First:&lt;/strong&gt; Use identity-first security and threat detection to protect the distributed nodes that collect your data.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;BYOC represents the maturity of the cloud era. It offers the speed and intelligence of a &lt;strong&gt;fully managed Kafka&lt;/strong&gt; platform with the absolute control of a private data center.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions (FAQs)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What makes Condense different from other BYOC Kafka platforms?&amp;nbsp;&lt;br&gt;&lt;br&gt;
Unlike platforms where BYOC is an afterthought, Condense is 100% BYOC-native. It is engineered to run entirely within your VPC (AWS, Azure, or GCP), ensuring that 100% of your data remains under your ownership while eliminating "SaaS" networking taxes and egress fees.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How does Condense handle scaling without manual intervention?&amp;nbsp; Condense features Autonomous Scaling. It monitors real-time consumer lag and event throughput, automatically provisioning compute for your custom Java, Python, or Go transforms. When surges pass, it scales back down to optimize costs, removing the need for a dedicated DevOps team to size clusters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does Condense support real-time data processing?&amp;nbsp;&lt;br&gt;&lt;br&gt;
Yes. Condense provides a Unified Streaming Layer that merges the broker and application environment. By running application logic "local" to the Kafka broker, it achieves Zero-Hop processing, which eliminates the network latency found in external processing tiers like Flink.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How does Condense ensure compliance with the DPDP Act in India?&amp;nbsp;&lt;br&gt;&lt;br&gt;
By using a managed BYOC model, Condense satisfies the DPDP Act’s strict data residency requirements. All sensitive telemetry is stored and processed within India’s borders, and with Customer-Managed Keys (CMK), even the platform provider cannot access your decrypted data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can I use Condense to build industry-specific AI pipelines?&amp;nbsp;&lt;br&gt;&lt;br&gt;
Yes. Condense includes a Verticalized Ecosystem with pre-built, domain-aware transforms. For industries like Mobility (VIN parsing, trip decoding) or FinTech, these pre-tuned assets allow R&amp;amp;D teams to bypass months of custom coding and go to market faster.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How do Condense AI Agents assist in operations?&amp;nbsp;&lt;br&gt;&lt;br&gt;
Condense uses specialized AI Agents for Intelligent Observability. These agents monitor event streams and infrastructure (K8s/Kafka) continuously, providing actionable insights and automated failovers, which reduces the Total Cost of Ownership (TCO) by up to 40%.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>bringyourowncloud</category>
      <category>datastreams</category>
      <category>data</category>
      <category>dataengineering</category>
    </item>
    <item>
      <title>Real-Time Inventory Management with Kafka: How Retailers Are Eliminating Stockouts</title>
      <dc:creator>Sachin Kamath</dc:creator>
      <pubDate>Fri, 10 Jul 2026 06:37:45 +0000</pubDate>
      <link>https://dev.to/zeliotofficial/real-time-inventory-management-with-kafka-how-retailers-are-eliminating-stockouts-4eoe</link>
      <guid>https://dev.to/zeliotofficial/real-time-inventory-management-with-kafka-how-retailers-are-eliminating-stockouts-4eoe</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Retailers process thousands of inventory transactions every second across physical stores, eCommerce platforms, warehouses, suppliers, and fulfillment centers. Yet many inventory systems still rely on scheduled synchronization, causing stock levels to become outdated within minutes. The result is overselling, delayed replenishment, inaccurate inventory visibility, and avoidable stockouts.&lt;/p&gt;

&lt;p&gt;Apache Kafka enables real-time inventory management by treating every inventory movement as an event that is streamed the moment it occurs. Sales, returns, warehouse transfers, supplier deliveries, and IoT sensor updates are continuously processed to maintain a consistent inventory view across all retail systems.&lt;/p&gt;

&lt;p&gt;This event-driven approach helps retailers improve inventory accuracy, automate replenishment, detect stockouts before they occur, and respond to changing demand in near real time.&lt;/p&gt;

&lt;p&gt;In this guide, you'll learn how Apache Kafka powers real-time inventory management, explore a production-ready reference architecture, understand how inventory events are processed across retail systems, and discover implementation best practices for building scalable, resilient inventory streaming applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Retail inventory management has evolved far beyond tracking products on warehouse shelves. Today's retailers operate across physical stores, eCommerce platforms, online marketplaces, distribution centers, and supplier networks, where inventory levels change continuously throughout the day. Every sale, return, warehouse transfer, supplier delivery, and inventory adjustment impacts product availability, making accurate inventory visibility essential for delivering a seamless customer experience.&lt;/p&gt;

&lt;p&gt;However, many retailers still rely on scheduled synchronization between Point-of-Sale (POS) systems, Warehouse Management Systems (WMS), Enterprise Resource Planning (ERP) platforms, and online storefronts. While these systems perform different functions, they all depend on accurate inventory data. When updates occur only every few minutes, hourly, or overnight, each application gradually develops its own view of inventory, leading to inconsistent stock levels across the business.&lt;/p&gt;

&lt;p&gt;This lack of synchronization creates operational challenges that extend beyond inventory accuracy. Customers may order products that are no longer available, store associates struggle to locate stock, replenishment teams react too late to changing demand, and forecasting models rely on outdated information. As retailers expand across multiple sales channels, traditional inventory synchronization becomes increasingly difficult to scale.&lt;/p&gt;

&lt;p&gt;Apache Kafka addresses these challenges by enabling real-time inventory management through event streaming. Instead of periodically exchanging inventory data, every inventory movement is published as an event and shared immediately with the systems that need it. This event-driven approach keeps inventory synchronized across retail applications while enabling capabilities such as real-time stock tracking, proactive stockout detection, automated replenishment, and demand sensing.&lt;/p&gt;

&lt;p&gt;In this guide, we'll explore how retailers use Apache Kafka to build scalable, event-driven inventory platforms, examine a production-ready reference architecture, and discuss implementation best practices for reducing stockouts and improving inventory visibility across the supply chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Traditional Inventory Management Creates Stockouts
&lt;/h2&gt;

&lt;p&gt;Retail inventory changes continuously. Every customer purchase, online order, return, warehouse transfer, supplier delivery, and inventory adjustment affects product availability. While these events happen in real time, many retail systems still exchange inventory data on a fixed schedule, creating a gap between actual inventory and what different applications believe is available.&lt;/p&gt;

&lt;p&gt;As retailers expand across physical stores, eCommerce platforms, marketplaces, and fulfillment centers, this delay becomes increasingly difficult to manage. Inventory may be available in one system but unavailable in another, leading to inconsistent stock visibility, delayed replenishment, and dissatisfied customers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with Nightly Batch Inventory Synchronization
&lt;/h2&gt;

&lt;p&gt;For years, retailers relied on batch processing to synchronize inventory between operational systems. Scheduled jobs, file transfers, or periodic API calls updated inventory at fixed intervals, often every hour or overnight. While this approach reduced integration complexity, it also meant inventory data remained outdated until the next synchronization cycle.&lt;/p&gt;

&lt;p&gt;A typical retail ecosystem includes several independent systems, each maintaining its own inventory records.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Point-of-Sale (POS) systems&lt;/li&gt;
&lt;li&gt;Warehouse Management Systems (WMS)&lt;/li&gt;
&lt;li&gt;Enterprise Resource Planning (ERP) platforms&lt;/li&gt;
&lt;li&gt;eCommerce applications&lt;/li&gt;
&lt;li&gt;Supplier management systems&lt;/li&gt;
&lt;li&gt;Mobile inventory applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without continuous synchronization, these systems gradually develop different views of inventory throughout the day.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Synchronization Method&lt;/th&gt;
&lt;th&gt;Update Frequency&lt;/th&gt;
&lt;th&gt;Business Impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Nightly batch jobs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Every 24 hours&lt;/td&gt;
&lt;td&gt;Inventory remains outdated for most of the day.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hourly synchronization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Every 60 minutes&lt;/td&gt;
&lt;td&gt;Delayed visibility into inventory changes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API polling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Every 5–30 minutes&lt;/td&gt;
&lt;td&gt;Higher infrastructure overhead with stale data between polls.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Event streaming&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Continuous&lt;/td&gt;
&lt;td&gt;Inventory is updated as business events occur.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Even a short synchronization delay can have a significant business impact. During promotional campaigns or peak shopping periods, inventory may change hundreds of times before the next scheduled update, increasing the risk of overselling and stockouts.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Organizations moving away from scheduled synchronization often begin by replacing traditional ETL pipelines with streaming architectures. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How Inventory Becomes Inconsistent Across Retail Systems
&lt;/h2&gt;

&lt;p&gt;Consider a retailer that starts the day with 150 units of a product in stock.&lt;/p&gt;

&lt;p&gt;During the day, customers purchase products in-store, online orders reserve inventory, and warehouses replenish stock. Each system records these activities independently, but until the next synchronization cycle, every application reports a different inventory value.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Business Event&lt;/th&gt;
&lt;th&gt;Actual Inventory&lt;/th&gt;
&lt;th&gt;ERP&lt;/th&gt;
&lt;th&gt;Online Store&lt;/th&gt;
&lt;th&gt;POS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Opening inventory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;150&lt;/td&gt;
&lt;td&gt;150&lt;/td&gt;
&lt;td&gt;150&lt;/td&gt;
&lt;td&gt;150&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;12 products sold in-store&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;138&lt;/td&gt;
&lt;td&gt;150&lt;/td&gt;
&lt;td&gt;150&lt;/td&gt;
&lt;td&gt;138&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;8 online orders placed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;130&lt;/td&gt;
&lt;td&gt;150&lt;/td&gt;
&lt;td&gt;142&lt;/td&gt;
&lt;td&gt;138&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Warehouse replenishment received&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;170&lt;/td&gt;
&lt;td&gt;150&lt;/td&gt;
&lt;td&gt;142&lt;/td&gt;
&lt;td&gt;138&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scheduled synchronization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;170&lt;/td&gt;
&lt;td&gt;170&lt;/td&gt;
&lt;td&gt;170&lt;/td&gt;
&lt;td&gt;170&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For several hours, every system maintains a different inventory count. While the POS reflects recent sales, the ERP and online store continue operating with outdated information until synchronization completes.&lt;/p&gt;

&lt;p&gt;This inconsistency creates several operational challenges.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Customers purchase products that are no longer available.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Online channels display incorrect stock levels.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Replenishment teams respond too late to inventory changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Store associates struggle to locate available inventory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Safety stock increases to compensate for poor inventory visibility.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Demand forecasting relies on outdated inventory data.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As inventory volumes grow across multiple channels, these issues become increasingly difficult to solve using scheduled synchronization alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Apache Kafka Enables Real-Time Inventory Management
&lt;/h2&gt;

&lt;p&gt;Instead of synchronizing inventory databases at scheduled intervals, Apache Kafka enables retailers to process every inventory movement as an event the moment it occurs. Each business event—whether it's a product sale, customer return, warehouse transfer, or supplier delivery—is published to Kafka and made available to every downstream application in real time.&lt;/p&gt;

&lt;p&gt;This event-driven approach ensures that inventory changes are shared continuously rather than periodically. As new events arrive, systems such as ERP, WMS, eCommerce platforms, analytics applications, and mobile inventory tools consume the same stream independently, allowing them to maintain a consistent view of inventory without relying on frequent database synchronization.&lt;/p&gt;

&lt;p&gt;Beyond improving inventory visibility, this architecture decouples producers and consumers. A POS system only needs to publish a sales event once, while multiple downstream services can consume and process that event according to their own business requirements. This simplifies system integration, reduces operational complexity, and allows retail applications to scale independently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inventory Events That Drive Real-Time Stock Tracking
&lt;/h2&gt;

&lt;p&gt;An effective real-time inventory management system captures every business event that changes inventory availability. Rather than streaming only sales transactions, retailers continuously publish events from across the supply chain to build an accurate and up-to-date inventory state.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event Source&lt;/th&gt;
&lt;th&gt;Inventory Event&lt;/th&gt;
&lt;th&gt;Business Outcome&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;POS System&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Product sold&lt;/td&gt;
&lt;td&gt;Reduce available inventory immediately&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;eCommerce Platform&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Order placed or cancelled&lt;/td&gt;
&lt;td&gt;Synchronize inventory across sales channels&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Warehouse Management System&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Inventory received, picked, packed, or transferred&lt;/td&gt;
&lt;td&gt;Maintain warehouse inventory accuracy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Supplier System&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shipment dispatched or delivered&lt;/td&gt;
&lt;td&gt;Track incoming inventory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ERP&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Inventory adjustments and purchase orders&lt;/td&gt;
&lt;td&gt;Keep enterprise inventory aligned&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Returns Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Product returned&lt;/td&gt;
&lt;td&gt;Restore sellable inventory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Smart Shelf Sensors&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Item removed or shelf replenished&lt;/td&gt;
&lt;td&gt;Monitor physical inventory in real time&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Together, these events create a continuous stream of inventory activity that reflects what is happening across the business at any given moment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From Business Events to a Unified Inventory View&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unlike traditional integrations, where every application communicates directly with multiple systems, Apache Kafka acts as a central event backbone.&lt;/p&gt;

&lt;p&gt;When a product is sold, the POS system publishes a sales event to Kafka. The Inventory Service consumes the event and updates the available stock. At the same time, the ERP, warehouse management system, eCommerce platform, analytics tools, and monitoring dashboards can independently consume the same event without requiring additional integrations.&lt;/p&gt;

&lt;p&gt;This publish-and-subscribe model enables retailers to build loosely coupled systems that remain synchronized while reducing the complexity of maintaining dozens of point-to-point integrations.&lt;/p&gt;

&lt;p&gt;By processing every inventory event as it occurs, retailers gain a near real-time view of stock availability across stores, warehouses, and online channels. This provides the foundation for capabilities such as real-time stock tracking, automated replenishment, demand sensing, and proactive stockout detection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-Time Inventory Management Architecture with Apache Kafka
&lt;/h2&gt;

&lt;p&gt;A production-ready inventory platform combines operational systems, IoT devices, event streaming, and stream processing to maintain a continuously updated view of inventory across the retail ecosystem.&lt;/p&gt;

&lt;p&gt;Instead of synchronizing inventory databases, every inventory movement is published as an event and processed in real time. This ensures that all downstream applications receive the same information as soon as it becomes available.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fowhfjbtqgpbvgyj0v24v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fowhfjbtqgpbvgyj0v24v.png" alt="Real-Time Inventory Management Architecture with Apache Kafka" width="800" height="750"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every system publishes only the events it owns. A POS system publishes completed sales, warehouse systems publish inventory movements, suppliers publish shipment updates, and smart shelf sensors report physical inventory changes. Kafka distributes these events to every downstream consumer, allowing each application to process the same inventory stream independently.&lt;/p&gt;

&lt;p&gt;This architecture eliminates point-to-point integrations and provides a single event backbone for inventory operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using MQTT for Real-Time Shelf Monitoring
&lt;/h2&gt;

&lt;p&gt;While transactional systems capture sales and warehouse operations, they often don't detect what happens on the store floor before a transaction occurs.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A customer removes an item from a shelf.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A store associate replenishes inventory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Products are moved to a different display.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Items are misplaced or damaged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Shelf inventory reaches a critical threshold.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These events are invisible to traditional inventory systems until a manual inventory count or a sales transaction updates the database.&lt;/p&gt;

&lt;p&gt;Smart shelves equipped with RFID readers, weight sensors, barcode scanners, or computer vision systems can continuously publish these changes using MQTT. An MQTT source connector ingests these events into Kafka, making them immediately available to inventory services, ERP platforms, monitoring dashboards, and analytics applications.&lt;/p&gt;

&lt;p&gt;For organizations building IoT-enabled retail solutions, MQTT connectors simplify the ingestion of real-time device data into streaming pipelines. &lt;/p&gt;

&lt;h2&gt;
  
  
  Simplifying Retail Inventory Pipelines with Condense
&lt;/h2&gt;

&lt;p&gt;Building the architecture above involves more than deploying an Apache Kafka cluster. Engineering teams must integrate data from retail applications, ingest IoT events, process inventory streams, monitor pipeline health, and ensure the platform scales reliably as transaction volumes grow.&lt;/p&gt;

&lt;p&gt;Condense simplifies these operational challenges by providing a unified platform for building and managing real-time streaming applications. With fully managed Kafka, enterprise connectors, visual pipeline development, and built-in stream processing, teams can develop production-ready inventory pipelines without managing the underlying streaming infrastructure.&lt;/p&gt;

&lt;p&gt;For retail inventory workloads, Condense enables teams to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Ingest events from POS systems, ERP platforms, warehouses, suppliers, databases, and MQTT-enabled devices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Design and deploy inventory pipelines through a visual interface or code-based workflows.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Process inventory events using built-in transformations and stream processing capabilities.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Monitor pipeline health, throughput, and consumer performance from a centralized dashboard.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deploy securely within their own cloud environment using a Bring Your Own Cloud (BYOC) model.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By abstracting much of the operational complexity, Condense allows engineering teams to focus on building inventory applications instead of maintaining the streaming platform that powers them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detecting Stockouts and Predicting Demand
&lt;/h2&gt;

&lt;p&gt;Real-time inventory management isn't just about knowing how many products are available. The real value comes from continuously analyzing inventory events to detect potential stockouts, automate replenishment, and respond to changing customer demand before it impacts sales.&lt;/p&gt;

&lt;p&gt;With Apache Kafka acting as the event backbone, retailers can correlate events from multiple systems as they occur, creating a live inventory view that reflects the current state of every product across stores, warehouses, and fulfillment centers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Correlating Inventory Events in Real Time
&lt;/h2&gt;

&lt;p&gt;A stockout rarely occurs because inventory suddenly reaches zero. More often, it happens because different systems have different views of inventory.&lt;/p&gt;

&lt;p&gt;Consider a common retail scenario:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A customer purchases the last two units of a product in a store.&lt;/li&gt;
&lt;li&gt;The POS system immediately records the sale.&lt;/li&gt;
&lt;li&gt;A warehouse has already dispatched replacement inventory.&lt;/li&gt;
&lt;li&gt;The shipment is still in transit.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The ERP continues to show inventory as available because the latest warehouse update hasn't been processed.&lt;/p&gt;

&lt;p&gt;Without a shared event stream, each system operates independently, making it difficult to determine the true inventory position.&lt;/p&gt;

&lt;p&gt;By streaming these events through Apache Kafka, retailers can correlate sales, warehouse movements, supplier deliveries, and inventory updates as they occur. Instead of waiting for scheduled synchronization, every new event contributes to a continuously updated inventory state.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event Source&lt;/th&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Inventory Impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;POS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Product sold&lt;/td&gt;
&lt;td&gt;Reduce available inventory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Warehouse&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shipment dispatched&lt;/td&gt;
&lt;td&gt;Inventory replenishment in transit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Store Receiving&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shipment received&lt;/td&gt;
&lt;td&gt;Increase available inventory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Supplier&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Delivery confirmed&lt;/td&gt;
&lt;td&gt;Update inbound inventory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Shelf Sensor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shelf empty&lt;/td&gt;
&lt;td&gt;Confirm physical stock depletion&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This continuous event processing enables inventory services to maintain an accurate inventory position while ensuring every downstream application works with the same information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-Time Stock Tracking Across Retail Channels
&lt;/h2&gt;

&lt;p&gt;Modern inventory exists in multiple locations simultaneously. The same product may be available in a retail store, regional warehouse, fulfillment center, or online marketplace.&lt;/p&gt;

&lt;p&gt;As inventory moves between these locations, every change needs to be reflected across all customer-facing and operational systems.&lt;/p&gt;

&lt;p&gt;With an event-driven architecture, each inventory movement is published once and consumed by multiple applications independently. This enables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consistent inventory visibility across physical and online channels.&lt;/li&gt;
&lt;li&gt;Faster inventory updates for ERP, WMS, and eCommerce platforms.&lt;/li&gt;
&lt;li&gt;Improved order allocation and fulfillment decisions.&lt;/li&gt;
&lt;li&gt;Reduced risk of overselling.&lt;/li&gt;
&lt;li&gt;Better inventory accuracy across the retail network.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of synchronizing databases throughout the day, retailers continuously update inventory as business events occur.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Streaming Data for Demand Sensing
&lt;/h2&gt;

&lt;p&gt;Traditional forecasting models primarily rely on historical sales reports. While useful for long-term planning, they often fail to capture sudden changes in customer demand caused by promotions, seasonal events, regional trends, or unexpected buying patterns.&lt;/p&gt;

&lt;p&gt;Streaming data provides a more dynamic approach.&lt;/p&gt;

&lt;p&gt;As inventory events flow through Kafka, retailers can continuously evaluate metrics such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Current sales velocity&lt;/li&gt;
&lt;li&gt;Inventory depletion rate&lt;/li&gt;
&lt;li&gt;Product return patterns&lt;/li&gt;
&lt;li&gt;Warehouse replenishment frequency&lt;/li&gt;
&lt;li&gt;Supplier lead times&lt;/li&gt;
&lt;li&gt;Regional demand trends&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rather than generating reports at the end of the day, these metrics are updated continuously, giving supply chain teams a real-time view of changing demand.&lt;/p&gt;

&lt;p&gt;This allows retailers to identify fast-moving products earlier, prioritize replenishment, and make inventory decisions based on current business activity instead of historical snapshots.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enabling Automated Restocking
&lt;/h2&gt;

&lt;p&gt;Once inventory events are available as a continuous stream, retailers can automate replenishment based on predefined business rules.&lt;/p&gt;

&lt;p&gt;For example, a stream processing application can evaluate conditions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shelf inventory falls below the minimum threshold.&lt;/li&gt;
&lt;li&gt;Sales velocity exceeds the expected rate.&lt;/li&gt;
&lt;li&gt;Replacement inventory is available in a nearby warehouse.&lt;/li&gt;
&lt;li&gt;Supplier lead times remain within acceptable limits.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When these conditions are met, the application can automatically generate a restocking recommendation or notify store operations before customers encounter empty shelves.&lt;/p&gt;

&lt;p&gt;By combining real-time stock tracking with continuous event processing, retailers shift from reacting to stockouts after they occur to preventing them altogether. This improves product availability, reduces lost sales, and enables more responsive inventory operations across the retail network.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for Building Real-Time Inventory Management Pipelines
&lt;/h2&gt;

&lt;p&gt;Building a real-time inventory management platform requires more than deploying Apache Kafka. Retailers need to ensure inventory events are accurate, ordered, scalable, and resilient as transaction volumes grow across stores, warehouses, suppliers, and online channels.&lt;/p&gt;

&lt;p&gt;The following best practices help engineering teams build reliable inventory streaming applications while maintaining inventory consistency across the business.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design Events Around Business Activities&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of publishing periodic inventory snapshots, publish business events that represent changes to inventory.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product Sold&lt;/li&gt;
&lt;li&gt;Inventory Reserved&lt;/li&gt;
&lt;li&gt;Inventory Released&lt;/li&gt;
&lt;li&gt;Goods Received&lt;/li&gt;
&lt;li&gt;Warehouse Transfer Completed&lt;/li&gt;
&lt;li&gt;Customer Return Processed&lt;/li&gt;
&lt;li&gt;Inventory Adjusted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An event-driven model preserves the complete history of inventory changes, making it easier to replay events, audit inventory movement, and recover application state when needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Organize Topics for Scalability&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create dedicated Kafka topics for different inventory event types instead of combining unrelated events into a single stream.&lt;/p&gt;

&lt;p&gt;A common topic strategy includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sales-events&lt;/li&gt;
&lt;li&gt;Returns-events&lt;/li&gt;
&lt;li&gt;Warehouse-events&lt;/li&gt;
&lt;li&gt;Supplier-events&lt;/li&gt;
&lt;li&gt;Inventory-adjustments&lt;/li&gt;
&lt;li&gt;shelf-events&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation simplifies event processing, improves scalability, and allows individual consumers to subscribe only to the events they require.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Preserve Event Ordering&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Inventory updates for the same product should always be processed in sequence.&lt;/p&gt;

&lt;p&gt;Partitioning topics using business identifiers such as SKU ID, Store ID, or Warehouse ID helps maintain event ordering while allowing the platform to scale horizontally.&lt;/p&gt;

&lt;p&gt;Proper partitioning reduces the risk of inventory inconsistencies caused by out-of-order processing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitor Streaming Pipelines Continuously
&lt;/h2&gt;

&lt;p&gt;Operational visibility is essential for maintaining a healthy streaming platform.&lt;/p&gt;

&lt;p&gt;Engineering teams should continuously monitor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consumer lag&lt;/li&gt;
&lt;li&gt;Processing latency&lt;/li&gt;
&lt;li&gt;Event throughput&lt;/li&gt;
&lt;li&gt;Failed messages&lt;/li&gt;
&lt;li&gt;Topic storage utilization&lt;/li&gt;
&lt;li&gt;Consumer availability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Monitoring these metrics helps identify bottlenecks before they impact inventory accuracy or downstream applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secure and Validate Inventory Events
&lt;/h2&gt;

&lt;p&gt;Because inventory data directly influences purchasing, fulfillment, and replenishment decisions, every event should be validated before it updates inventory state.&lt;/p&gt;

&lt;p&gt;Production deployments should also implement encryption, role-based access control, and schema validation to ensure inventory data remains secure and consistent across all connected systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementation Checklist&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before deploying a real-time inventory management platform, verify the following:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Event Design&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Publish business events instead of inventory snapshots.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Topic Strategy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use dedicated topics for sales, returns, warehouse, supplier, and inventory events.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Partitioning&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Partition by SKU, Store ID, or Warehouse ID to preserve event ordering.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Schema Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use versioned schemas to support application evolution.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Consumer Scaling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Scale consumer groups independently based on workload.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Monitoring&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Track consumer lag, throughput, processing latency, and failed events.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Encrypt data in transit and implement role-based access control.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Resilience&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Configure replication, retries, and disaster recovery for high availability.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Following these practices helps retailers build scalable inventory streaming pipelines that maintain accurate inventory visibility while supporting millions of inventory events across distributed retail operations.&lt;/p&gt;

&lt;p&gt;Building Real-Time Inventory Applications with Condense&lt;/p&gt;

&lt;p&gt;Apache Kafka provides the event streaming foundation for real-time inventory management, but building a production application requires more than moving events between systems. Inventory events need to be transformed, enriched with business context, validated, routed to downstream applications, and monitored throughout their lifecycle.&lt;/p&gt;

&lt;p&gt;Condense extends Apache Kafka with a unified application platform that enables engineering teams to build, deploy, and operate these event-driven applications without assembling multiple development and operational tools.&lt;/p&gt;

&lt;p&gt;For a retail inventory use case, a typical application built on Condense can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Enrich POS events with product and store metadata before updating inventory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Correlate sales, warehouse, supplier, and shelf events to maintain a real-time inventory state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Trigger restocking workflows when inventory falls below predefined thresholds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Route inventory updates to ERP, WMS, eCommerce platforms, analytics systems, and operational dashboards from a single processing pipeline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Monitor application performance, processing latency, and event flow throughout the pipeline.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By combining application development, stream processing, deployment, and operations in a single platform, Condense enables teams to focus on delivering business logic instead of integrating and maintaining multiple components across the streaming stack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Modern retail depends on accurate and timely inventory information. As businesses expand across physical stores, eCommerce platforms, warehouses, and supplier networks, scheduled inventory synchronization can no longer keep pace with the volume and speed of inventory changes.&lt;/p&gt;

&lt;p&gt;By adopting real-time inventory management with Apache Kafka, retailers can process inventory events as they occur, maintaining a consistent view of stock across every operational system. This event-driven approach supports real-time stock tracking, faster replenishment, proactive stockout detection, and demand sensing, enabling retailers to respond quickly to changing customer demand.&lt;/p&gt;

&lt;p&gt;Building these applications requires more than a messaging platform. Teams need the ability to develop, deploy, operate, and scale event-driven applications that transform inventory events into business outcomes. Condense simplifies this process by providing a unified platform for building production-ready streaming applications on Apache Kafka, enabling retailers to accelerate development while maintaining the flexibility and scalability of an event-driven architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frequently Asked Questions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What is real-time inventory management? &lt;br&gt;
Real-time inventory management continuously updates inventory as business events occur instead of relying on scheduled synchronization. Every sale, return, warehouse transfer, supplier delivery, or inventory adjustment immediately updates inventory across connected systems, providing accurate stock visibility throughout the retail network.&lt;/p&gt;

&lt;p&gt;Why is Apache Kafka used for inventory management?&lt;br&gt;
Apache Kafka acts as the event backbone for inventory management. It enables retailers to stream inventory events in real time so that POS systems, ERP platforms, Warehouse Management Systems (WMS), eCommerce applications, and analytics services all consume the same inventory data without relying on batch synchronization.&lt;/p&gt;

&lt;p&gt;How does event-driven inventory management reduce stockouts? &lt;br&gt;
Event-driven inventory management processes inventory events as they occur. By correlating sales, returns, warehouse transfers, supplier deliveries, and shelf events in real time, retailers can detect low inventory sooner, trigger replenishment workflows automatically, and maintain accurate inventory across every sales channel.&lt;/p&gt;

&lt;p&gt;Can Apache Kafka integrate with existing retail systems? &lt;br&gt;
Yes. Apache Kafka integrates with systems such as POS, ERP, Warehouse Management Systems (WMS), supplier applications, eCommerce platforms, databases, and IoT devices. This allows organizations to modernize inventory management without replacing existing business applications.&lt;/p&gt;

&lt;p&gt;How do MQTT-enabled shelf sensors improve inventory visibility? &lt;br&gt;
Smart shelves equipped with RFID readers, barcode scanners, weight sensors, or computer vision systems publish inventory events using MQTT. These events are streamed into Kafka, providing near real-time visibility into shelf inventory and enabling faster replenishment decisions.&lt;/p&gt;

&lt;p&gt;What role does Condense play in a real-time inventory architecture? &lt;br&gt;
While Apache Kafka provides the event streaming foundation, Condense provides the application platform for building inventory solutions on top of Kafka. Teams can develop applications that correlate inventory events, maintain inventory state, automate replenishment workflows, expose APIs, and deploy production-ready streaming applications without assembling multiple development and operational tools.&lt;/p&gt;

&lt;p&gt;Why build inventory applications with Condense instead of using Apache Kafka alone? &lt;br&gt;
Apache Kafka excels at transporting and storing events, but production applications also require business logic, application development, deployment, monitoring, lifecycle management, and operations. Condense brings these capabilities together in a unified platform, allowing engineering teams to focus on solving business problems instead of integrating and maintaining multiple frameworks.&lt;/p&gt;

&lt;p&gt;Can Condense work with an existing Kafka deployment? &lt;br&gt;
Yes. Condense is designed to build and run applications on existing Apache Kafka deployments, including self-managed Kafka clusters, managed Kafka services, and Bring Your Own Cloud (BYOC) environments. Organizations can continue using their preferred Kafka infrastructure while accelerating application development and operations.&lt;/p&gt;

&lt;p&gt;How does Condense accelerate the development of retail streaming applications? &lt;br&gt;
Condense combines application development, stream processing, deployment, observability, and lifecycle management into a single platform. This enables engineering teams to move from architecture to production faster while reducing the operational effort required to build and maintain event-driven inventory applications.&lt;/p&gt;

&lt;p&gt;Is this architecture suitable only for retail inventory management? &lt;br&gt;
No. The same event-driven architecture can be applied to connected manufacturing, logistics, supply chain visibility, fleet management, healthcare, industrial IoT, and other industries where business decisions depend on processing continuous streams of real-time events.&lt;/p&gt;

</description>
      <category>kafka</category>
      <category>inventorymanagement</category>
      <category>datastreaming</category>
      <category>eventdriven</category>
    </item>
    <item>
      <title>Unlock Kafka Schemas with Karapace: A Hands-On Guide</title>
      <dc:creator>Sachin Kamath</dc:creator>
      <pubDate>Thu, 18 Jun 2026 11:29:21 +0000</pubDate>
      <link>https://dev.to/zeliotofficial/unlock-kafka-schemas-with-karapace-a-hands-on-guide-4kp6</link>
      <guid>https://dev.to/zeliotofficial/unlock-kafka-schemas-with-karapace-a-hands-on-guide-4kp6</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Kafka handles event streaming: producers write to topics, consumers read. JSON parsing lags at scale, so use Karapace Schema Registry (open-source Confluent alternative) with Protobuf for efficient, schema-enforced serialization. This Java Spring Boot guide shows producer/consumer setup, compile .proto schemas, use TopicNameStrategy, SCRAM/Basic auth tested on Condense's Kafka+Karapace. Ideal for structured telematics; avoid for ad-hoc data.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Brief Introduction to Kafka
&lt;/h2&gt;

&lt;p&gt;Kafka is a distributed system consisting of servers and clients that communicate using the TCP network protocol. Kafka is used as an event-based system that records a specific event that has happened.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For example "Transaction of 500 USD has occurred in Alice's account."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Events are created and written to Kafka by client applications called Producers and consumed by client applications called Consumers. Kafka provides the feature to create topics, which can be used to group events as per the user's requirements. Single or multiple producers can produce events/messages to a single topic, and single or multiple consumers can consume from one topic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Throughput Issues When Operating at Scale
&lt;/h2&gt;

&lt;p&gt;By default, Kafka producers and consumers exchange event data in the String UTF-8 format. Even though Kafka offers features to compress the data using gzip and other algorithms, this creates additional overhead on the producers and consumers to decompress the data and then validate it. Most events are generally sent in the JSON format, which is helpful for human readability, but this slows down the whole pipeline if high throughput is needed. The effects can only be felt on production clusters where the incoming data transfer rate is high, but the consumers start lagging due to complex JSON deserialization if there are nested JSONs present.&lt;/p&gt;

&lt;p&gt;To overcome this issue, we need a different serialization and deserialization format that can reduce the time taken to construct or deconstruct the binary data sequence and ensure that the data follows a certain schema. We can either write our own serializer and deserializer or use open-source libraries from Confluent to achieve it. Confluent offers JSON, Avro, and Protobuf serde (serializer and deserializers) to compact the data and enforce a schema on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Karapace Schema Registry &amp;amp; Kafka
&lt;/h2&gt;

&lt;p&gt;Karapace is an open source near drop-in replacement for the Confluent Schema Registry, which aims to be compatible with the Confluent Schema Registry Client libraries, which are offered in Java, C#, etc. In this blog post, we will be looking at the Java libraries for implementing a producer and consumer.&lt;/p&gt;

&lt;p&gt;The Schema Registry is a separate component from Kafka, as it is not offered by Apache. It is designed to run as a separate node that is dependent on Kafka, but Kafka does not need Schema Registry as a core functionality. This can lead to confusion as Kafka does not enforce the schema for a particular topic or record, but the producer and consumer can choose to do so by using the Schema Registry. Unlike a relational database schema, where a table can enforce a very strict schema down to the datatypes, size of the data in a column, and other constraints regardless of the users connecting to it, different Kafka producers could still write very different data to a topic while not following a schema or format, causing downstream issues in a pipeline.&amp;nbsp; To avoid this, we can use different strategies to minimize the chances of schema drift or unintended data storage in topics, which we will cover in this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  DISCLAIMER
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Setting up Kafka and Schema Registry in a local environment requires a lot of configuration steps. I will be using a platform called Condense by the company Zeliot, which provides an integrated Kubernetes + Kafka + Schema Registry (Karapace), along with the options to set ACLs for Kafka and Schema Registry from a browser UI instead of a command line. I will cover setting up a local Kafka cluster with Schema Registry in a separate blog post.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Kafka &amp;amp; Schema Registry Work Together
&lt;/h2&gt;

&lt;p&gt;Since Kafka and Schema Registry are separate components, only the producers and consumers are responsible for setting up a loosely coupled connection between them. A basic flow diagram of how they work together is given below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw4q4d9qf4yvzlfpzfa2h.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw4q4d9qf4yvzlfpzfa2h.jpg" alt=" " width="799" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, this architecture assumes that we are using the Confluent Schema Registry Client in both the producer and consumer. We can use compiled classes without the Schema Registry, but that approach has disadvantages, such as a lack of versioning support without downtime, maintenance of compiled classes, complex logic, and library setup needed to generate and use compiled classes.&lt;/p&gt;

&lt;p&gt;With Kafka 4.0 and its KRaft-only architecture, schema registry compatibility is an important consideration for teams upgrading.&lt;/p&gt;

&lt;p&gt;The process of generating a message in JSON, Avro, or Protobuf format involves the producer specifying the naming strategy and version of the schema (default is the latest version), which is fetched from the Confluent client, and then we need to use the format-specific libraries as specified in the next sections to convert the message from String format to the required format. Note that the message format must be the same as specified in the schema type, or else the Kafka producer library will throw a serialization exception. After serialization, this message is sent to the Kafka topic, which is specified.&lt;/p&gt;

&lt;p&gt;For the consumer, the Confluent client library automatically sees the 1st byte called the magic byte, which determines whether the message is using the Schema Registry or not. 1 means yes and 0 means no. If yes, the next 4 bytes of the message determine the schema ID present in the Registry, and the client automatically fetches the correct schema for the message. Then the message is deserialized into the String UTF-8 format and can be viewed and processed normally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Subject Naming Strategies
&lt;/h2&gt;

&lt;p&gt;There are 3 different naming strategies offered by the Confluent Schema Registry Client libraries to determine how the serializer libraries fetch the schema to correctly serialize the message.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TopicName Strategy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the default strategy for naming the subject and is &lt;code&gt;&amp;lt;topic-name&amp;gt;&lt;/code&gt; + &lt;code&gt;”-value”&lt;/code&gt;. If a topic name is &lt;code&gt;car-topic&lt;/code&gt;, then the corresponding subject name is &lt;code&gt;car-topic-value&lt;/code&gt;. For the key, the subject name is &lt;code&gt;&amp;lt;topic-name&amp;gt;&lt;/code&gt; + &lt;code&gt;”-key”&lt;/code&gt;.  The serializer and deserializer using this strategy assume that all the messages in this topic correspond to this schema, and the presence of messages in other formats can disrupt the consumer with errors. Best used in cases where the topic name is used to differentiate the type of data present in the topic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RecordNameStrategy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a naming strategy for naming the subject using the record name of the schema (in the above example, the Record Name is Car). This does not tie the producer and consumer to a particular topic, but consuming messages in other formats/schemas can cause the consumer to crash if error-handling mechanisms aren’t implemented correctly. Best used in cases where producers need to immediately push data into any available topic with a high number of partitions, replication factors, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TopicRecordNameStrategy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This strategy uses both the topic name and the record name to determine the subject name. This strategy can be used when we are sure that a topic can have multiple record types.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up a Producer with Protobuf Schema
&lt;/h2&gt;

&lt;p&gt;First, we need to register a subject within Karapace, which defines the schema of the message containing the fields and their data types. I am defining the following proto schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="na"&gt;syntax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"proto3"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example.GenericProducer.schema&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;option&lt;/span&gt; &lt;span class="na"&gt;java_package&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"com.example.GenericProducer.schema"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;option&lt;/span&gt; &lt;span class="na"&gt;java_outer_classname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"CarProto"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;carId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;carNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="na"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="na"&gt;latitude&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="na"&gt;longitude&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This defines a schema in which the data should contain the fields carId, carNumber of type string, and speed, latitude, and longitude of type double. To get a higher data generation speed, I am using compiled classes for Protobuf.&lt;/p&gt;

&lt;p&gt;In your Spring Java project, create a folder &lt;code&gt;src/main/java&lt;/code&gt; named schema and create a file named Car.proto. Paste the above schema and modify your Java package and java_package to your requirements.&lt;/p&gt;

&lt;p&gt;Next, install the protobuf compiler for your OS by following the instructions &lt;a href="https://protobuf.dev/installation/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Next, go to the root directory of your project and enter the command to compile the proto file and generate a compiled class. Modify the path if needed. The first parameter sets the path for the output compiled class, and the second accepts the path for the proto file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;protoc &lt;span class="nt"&gt;--java_out&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;src/main/java/ src/main/java/schema/car.proto

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can check the generated file to see if it is created or not. Do not edit the file.&lt;/p&gt;

&lt;p&gt;Next, we can add the required dependencies  pom.xml for the producer application. Below are the following dependencies. We can use the latest versions of these libraries from the mvn repository and the Confluent repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt; 

  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.apache.kafka&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt; 

  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;kafka-clients&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt; 

  &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;3.9.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt; 

  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.confluent&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt; 

  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;kafka-protobuf-serializer&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt; 

  &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;8.0.1&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt; 

  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.confluent&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt; 

  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;kafka-protobuf-provider&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt; 

  &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;8.0.1&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt; 

  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.google.protobuf&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt; 

  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;protobuf-java&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt; 

  &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;4.33.4&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt; 

  &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;compile&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt; 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To add the io.confluent packages, we need to add the Confluent repository, as these packages are not present in the Maven repository.&lt;/p&gt;

&lt;p&gt;We can add it just before the &lt;code&gt;&amp;lt;/project&amp;gt;&lt;/code&gt; tag in the &lt;code&gt;pom.xml&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;...

&lt;span class="nt"&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;/plugins&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;/build&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;repositories&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;repository&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;confluent&lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;Confluent Maven Repository&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;https://packages.confluent.io/maven/&lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;/repository&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;/repositories&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;/project&amp;gt;&lt;/span&gt; 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since this is a sample producer, we shall randomly generate data every 5 seconds to Kafka to simulate telematics data. We shall define a class just like our schema.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;lombok.AllArgsConstructor&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;lombok.Data&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;lombok.NoArgsConstructor&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 


&lt;span class="nd"&gt;@Data&lt;/span&gt; 

&lt;span class="nd"&gt;@AllArgsConstructor&lt;/span&gt; 

&lt;span class="nd"&gt;@NoArgsConstructor&lt;/span&gt; 

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;carNumber&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;speed&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we shall define a KafkaProducer as a Spring component that can be invoked once within a service and reused.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt; 

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;KafkaProducerClient&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 


&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;FALSE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;CLIENT_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"car-producer"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;SECURITY_PROTOCOL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"SASL_PLAINTEXT"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;SASL_MECHANISM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"SCRAM-SHA-512"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;SASL_JAAS_CONFIG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"org.apache.kafka.common.security.scram.ScramLoginModule required username=\"%s\" password=\"%s\";"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;bootstrapServerUrl&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 


&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;KafkaProducerClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${kafka.bootstrap.server.url}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;bootstrapServerUrl&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bootstrapServerUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bootstrapServerUrl&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;KafkaProducer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getDefaultProducerClientWithoutPartitioner&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${schema.registry.url}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;schemaRegistryUrl&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="nc"&gt;Properties&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Properties&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ProducerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;KEY_SERIALIZER_CLASS_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;kafka&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;common&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;serialization&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;StringSerializer&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 


&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ProducerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;VALUE_SERIALIZER_CLASS_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"io.confluent.kafka.serializers.protobuf.KafkaProtobufSerializer"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 


&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ProducerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BOOTSTRAP_SERVERS_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bootstrapServerUrl&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ProducerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CLIENT_ID_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CLIENT_ID&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ProducerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RETRIES_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ProducerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;MAX_BLOCK_MS_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"3000"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AdminClientConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SECURITY_PROTOCOL_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;SECURITY_PROTOCOL&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SaslConfigs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SASL_MECHANISM&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;SASL_MECHANISM&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SaslConfigs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SASL_JAAS_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;SASL_JAAS_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AbstractKafkaSchemaSerDeConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SCHEMA_REGISTRY_URL_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;schemaRegistryUrl&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"basic.auth.credentials.source"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"USER_INFO"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"basic.auth.user.info"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;":"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AbstractKafkaSchemaSerDeConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AUTO_REGISTER_SCHEMAS&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AbstractKafkaSchemaSerDeConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;LATEST_COMPATIBILITY_STRICT&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AbstractKafkaSchemaSerDeConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;VALUE_SUBJECT_NAME_STRATEGY&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;  

&lt;span class="s"&gt;"io.confluent.kafka.serializers.subject.TopicNameStrategy"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;KafkaProducer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we set the properties of the key and value serializers to String and Protobuf, respectively. We then set the authentication mechanism for the Kafka cluster (SCRAM-SHA-512 in my case) with the username and password.&lt;/p&gt;

&lt;p&gt;I am using basic authentication in Karapace, so we need to set the &lt;code&gt;"basic.auth.credentials.source"&lt;/code&gt; to &lt;code&gt;“USER_INFO”&lt;/code&gt; which sets the KafkaProducer property to authenticate with the Schema registry using the Basic Authentication headers. We then need to set &lt;code&gt;"basic.auth.user.info"&lt;/code&gt; the user’s credentials in the format shown in the code. If we are not using any authentication for the Schema Registry, we can omit these properties.&lt;/p&gt;

&lt;p&gt;I am using the Topic Name Strategy for subjects for simplicity and demo purposes for the &lt;code&gt;AbstractKafkaSchemaSerDeConfig.VALUE_SUBJECT_NAME_STRATEGY&lt;/code&gt; property. We can set &lt;code&gt;AUTO_REGISTER_SCHEMAS&lt;/code&gt; to true if the schema doesn’t exist in the registry, or it will create a new version of the schema if the underlying compiled class schema has changed. The created subject will follow the naming strategy as defined in the above property. To allow compatibility between various versions and generate messages, we have set the &lt;code&gt;LATEST_COMPATIBILITY_STRICT&lt;/code&gt; to false.&lt;/p&gt;

&lt;p&gt;Now, we shall set up a random data generator class to generate some sample data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt; 

&lt;span class="nd"&gt;@NoArgsConstructor&lt;/span&gt; 

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RandomCarDataGenerator&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 


&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${CAR_ID}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;carIDString&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 


&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${CAR_NUMBER}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;carNumberString&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 


&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Random&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Random&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; 


&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="nf"&gt;generateRandomCar&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="n"&gt;car&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; 

&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;carId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;carIDString&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;carNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;carNumberString&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 



&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carId&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;carId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"default-car-id"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carNumber&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;carNumber&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;carNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"default-car-number"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setCarId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setCarNumber&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carNumber&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setSpeed&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generateRandomSpeed&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; 

&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setLatitude&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generateRandomLatitude&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; 

&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setLongitude&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;generateRandomLongitude&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; 

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 


&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;generateRandomLatitude&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="c1"&gt;// Range: -90 to 90 &lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;180&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nextDouble&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 


&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;generateRandomLongitude&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="c1"&gt;// Range: -180 to 180 &lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;180&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;360&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nextDouble&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 


&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;generateRandomSpeed&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="c1"&gt;// Random speed between 0 and 180 km/h &lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nextDouble&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 


&lt;span class="nc"&gt;Next&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;we&lt;/span&gt; &lt;span class="n"&gt;shall&lt;/span&gt; &lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;producer&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;which&lt;/span&gt; &lt;span class="n"&gt;initializes&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="nc"&gt;KafkaProducer&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;lightweight&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;convert&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;generated&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="n"&gt;into&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="nc"&gt;Protobuf&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;earlier&lt;/span&gt; &lt;span class="n"&gt;generated&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nc"&gt;CarProto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Car&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nc"&gt;Ensure&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;environment&lt;/span&gt; &lt;span class="n"&gt;variables&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;configured&lt;/span&gt; &lt;span class="n"&gt;properly&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;avoid&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;


&lt;span class="nd"&gt;@Service&lt;/span&gt; 

&lt;span class="nd"&gt;@RequiredArgsConstructor&lt;/span&gt; 

&lt;span class="nd"&gt;@Slf4j&lt;/span&gt; 

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProtobufProducer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 



&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;PROTO_TOPIC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"test-schema-car-protobuf"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 



&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;KafkaProducerClient&lt;/span&gt; &lt;span class="n"&gt;kafkaProducerClient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;KafkaProducer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;CarProto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Car&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;protoProducer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 



&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${schema.registry.url}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;schemaRegistryUrl&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 



&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${kafka.username}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 



&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${kafka.password}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 



&lt;span class="nd"&gt;@PostConstruct&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;initProtoProducer&lt;/span&gt;&lt;span class="o"&gt;(){&lt;/span&gt; 

&lt;span class="n"&gt;protoProducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kafkaProducerClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDefaultProducerClientWithoutPartitioner&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; 

&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;schemaRegistryUrl&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 



&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;produceCarProto&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="c1"&gt;// Direct conversion from POJO to Protobuf - NO JSON overhead! &lt;/span&gt;

&lt;span class="nc"&gt;CarProto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Car&lt;/span&gt; &lt;span class="n"&gt;protoCar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CarProto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Car&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newBuilder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; 

&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setCarId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCarId&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; 

&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setCarNumber&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCarNumber&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; 

&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setSpeed&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getSpeed&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; 

&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setLatitude&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getLatitude&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; 

&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setLongitude&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getLongitude&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; 

&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; 



&lt;span class="nc"&gt;ProducerRecord&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;CarProto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Car&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;producerRecord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ProducerRecord&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="no"&gt;PROTO_TOPIC&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCarId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;protoCar&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;protoProducer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;producerRecord&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Produced Proto message topic={} partition={} offset={}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 

&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;topic&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;partition&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;offset&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error producing Proto message"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="o"&gt;});&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error producing Proto message"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code initializes an KafkaProducer at startup and whenever the &lt;code&gt;producerCarProto&lt;/code&gt; is called, the builder associated with the &lt;code&gt;CarProto.Car&lt;/code&gt; is built from the car object and a ProducerRecord is initialized with the &lt;code&gt;CarProto.Car&lt;/code&gt; type. Then the protobuf message is sent to the Kafka topic &lt;code&gt;test-schema-car-protobuf&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, we shall initialize a class to periodically send messages every 5 seconds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt; 

&lt;span class="nd"&gt;@RequiredArgsConstructor&lt;/span&gt; 

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProducerScheduleService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 



&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;RandomCarDataGenerator&lt;/span&gt; &lt;span class="n"&gt;carDataGenerator&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ProtobufProducer&lt;/span&gt; &lt;span class="n"&gt;protobufProducer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;AvroProducer&lt;/span&gt; &lt;span class="n"&gt;avroProducer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="nd"&gt;@Scheduled&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fixedRate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;produceCarToBothFormats&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="n"&gt;car&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;carDataGenerator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generateRandomCar&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// generate once &lt;/span&gt;

&lt;span class="nd"&gt;@Cleanup&lt;/span&gt; 

&lt;span class="nc"&gt;ExecutorService&lt;/span&gt; &lt;span class="n"&gt;executorService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Executors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newVirtualThreadPerTaskExecutor&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; 

&lt;span class="n"&gt;executorService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;submit&lt;/span&gt;&lt;span class="o"&gt;(()-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;protobufProducer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;produceCarProto&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will produce a Protobuf message to the Kafka topic every 5 seconds with random data.&lt;/p&gt;

&lt;p&gt;Similarly, we shall have a separate consumer that can consume messages from this topic and deserialize these messages faster than the normal String JSON format. Let us create a new Spring Boot service with a Kafka Consumer that is set up with a Protobuf deserializer and specifically requests this schema to deserialize the messages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt; 

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;KafkaConsumerClient&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 



&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;FALSE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;GROUP_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"car-consumer"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;CLIENT_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"car-consumer1"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;SECURITY_PROTOCOL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"SASL_PLAINTEXT"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;SASL_MECHANISM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"SCRAM-SHA-512"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;SASL_JAAS_CONFIG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"org.apache.kafka.common.security.scram.ScramLoginModule required username=\"%s\" password=\"%s\";"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;bootstrapServerUrl&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 



&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;KafkaConsumerClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${kafka.bootstrap.server.url}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;bootstrapServerUrl&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bootstrapServerUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bootstrapServerUrl&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 



&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;KafkaConsumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getDefaultConsumer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${schema.registry.url}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;schemaRegistryUrl&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt; 

&lt;span class="nc"&gt;Properties&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Properties&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ConsumerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BOOTSTRAP_SERVERS_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bootstrapServerUrl&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ConsumerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;KEY_DESERIALIZER_CLASS_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"org.apache.kafka.common.serialization.StringDeserializer"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ConsumerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;VALUE_DESERIALIZER_CLASS_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"io.confluent.kafka.serializers.protobuf.KafkaProtobufDeserializer"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ConsumerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GROUP_ID_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;GROUP_ID&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ConsumerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CLIENT_ID_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CLIENT_ID&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ConsumerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AUTO_OFFSET_RESET_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"earliest"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ConsumerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ENABLE_AUTO_COMMIT_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ConsumerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;MAX_POLL_RECORDS_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ConsumerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;MAX_POLL_INTERVAL_MS_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AdminClientConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SECURITY_PROTOCOL_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;SECURITY_PROTOCOL&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SaslConfigs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SASL_MECHANISM&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;SASL_MECHANISM&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SaslConfigs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SASL_JAAS_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;SASL_JAAS_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AbstractKafkaSchemaSerDeConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SCHEMA_REGISTRY_URL_CONFIG&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;schemaRegistryUrl&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"basic.auth.credentials.source"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"USER_INFO"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"basic.auth.user.info"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;":"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"specific.protobuf.value.type"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"com.example.schema.CarProto$Car"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;KafkaConsumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Here, we initialize a KafkaConsumer that has a String key deserializer and a Protobuf value deserializer. We can set the consumer group ID and client ID by using the &lt;code&gt;ConsumerConfig.GROUP_ID_CONFIG&lt;/code&gt; and &lt;code&gt;ConsumerConfig.CLIENT_ID_CONFIG&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We can set properties such as the auto reset, auto offset commit, and polling periods based on the requirements and hardware capabilities.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We need to set the Schema Registry URL in the properties and the authentication properties, if needed, just like the producer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since we are using the Topic Name Strategy for the subject, we are sure that all messages in this topic will be of the CarProto.Car schema for which we generated the compiled class in the producer.&amp;nbsp; This is an optional property and can be omitted if we are not sure all messages are of the same schema. This helps deserialize messages from the topic if there are multiple topics or the Record Naming Strategy or TopicRecord Naming Strategy is used.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We shall now create a consumer class that keeps running once the application is started.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.example.GenericConsumer.services&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.time.Duration&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Collections&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.concurrent.ExecutorService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.concurrent.Executors&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.concurrent.atomic.AtomicBoolean&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 



&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.apache.kafka.clients.consumer.ConsumerRecord&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.apache.kafka.clients.consumer.ConsumerRecords&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.apache.kafka.clients.consumer.KafkaConsumer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.apache.kafka.common.errors.WakeupException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.beans.factory.annotation.Value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.context.SmartLifecycle&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.stereotype.Service&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 



&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.example.GenericConsumer.clients.KafkaConsumerClient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.example.GenericConsumer.enums.KafkaDeserializerTypes&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.example.schema.CarProto.Car&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 



&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;lombok.RequiredArgsConstructor&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;lombok.extern.slf4j.Slf4j&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 



&lt;span class="nd"&gt;@Service&lt;/span&gt; 

&lt;span class="nd"&gt;@RequiredArgsConstructor&lt;/span&gt; 

&lt;span class="nd"&gt;@Slf4j&lt;/span&gt; 

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CarConsumerService&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;SmartLifecycle&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 



&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;KafkaConsumerClient&lt;/span&gt; &lt;span class="n"&gt;kafkaConsumerClient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 



&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${kafka.username}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 



&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${kafka.password}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 



&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${schema.registry.url}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;schemaRegistryUrl&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 



&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;PROTO_TOPIC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"test-schema-car-protobuf"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;ExecutorService&lt;/span&gt; &lt;span class="n"&gt;executorService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;KafkaConsumer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;AtomicBoolean&lt;/span&gt; &lt;span class="n"&gt;running&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AtomicBoolean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;started&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 



&lt;span class="nd"&gt;@Override&lt;/span&gt; 

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;started&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting Kafka consumer in virtual thread..."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="c1"&gt;// Create thread executor &lt;/span&gt;

&lt;span class="n"&gt;executorService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Executors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newSingleThreadExecutor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="nc"&gt;Thread&lt;/span&gt; &lt;span class="n"&gt;thread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"kafka-consumer-thread"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setDaemon&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="o"&gt;});&lt;/span&gt; 

&lt;span class="n"&gt;running&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;started&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="c1"&gt;// Submit consumer task to executor &lt;/span&gt;

&lt;span class="n"&gt;executorService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;submit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;consumeCar&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Kafka consumer started successfully"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 



&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;consumeCar&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;consumer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kafkaConsumerClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDefaultConsumer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; 

&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;  

&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;  

&lt;span class="n"&gt;schemaRegistryUrl&lt;/span&gt; 

&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;subscribe&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;singleton&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;PROTO_TOPIC&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt; 

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Subscribed to topic: {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;PROTO_TOPIC&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;running&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="nc"&gt;ConsumerRecords&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;poll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofMillis&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt; 

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ConsumerRecord&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;carRecord&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;records&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Consumed Car Record - Key: {}, Value: {}, Partition: {}, Offset: {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;  

&lt;span class="n"&gt;carRecord&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; 

&lt;span class="n"&gt;carRecord&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;  

&lt;span class="n"&gt;carRecord&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;partition&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; 

&lt;span class="n"&gt;carRecord&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;offset&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; 

&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;records&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commitAsync&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WakeupException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Consumer wakeup called, shutting down..."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error in consumer loop"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Closing Kafka consumer..."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;consumer&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofSeconds&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error closing consumer"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Kafka consumer closed"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 



&lt;span class="nd"&gt;@Override&lt;/span&gt; 

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Shutting down Kafka consumer service..."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;running&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;consumer&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;wakeup&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;executorService&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;executorService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;shutdown&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; 

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;executorService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;awaitTermination&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;concurrent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;TimeUnit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SECONDS&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Executor did not terminate in time, forcing shutdown"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;executorService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;shutdownNow&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;InterruptedException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Shutdown interrupted"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="n"&gt;executorService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;shutdownNow&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; 

&lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentThread&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;interrupt&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="n"&gt;started&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Kafka consumer service shutdown complete"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 



&lt;span class="nd"&gt;@Override&lt;/span&gt; 

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;isRunning&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;started&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 



&lt;span class="nd"&gt;@Override&lt;/span&gt; 

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;getPhase&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="c1"&gt;// Return a phase value to control startup order &lt;/span&gt;

&lt;span class="c1"&gt;// Higher values start later and stop earlier &lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;MAX_VALUE&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 



&lt;span class="nd"&gt;@Override&lt;/span&gt; 

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;isAutoStartup&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="c1"&gt;// Return true to start automatically when Spring context is ready &lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 



&lt;span class="nd"&gt;@Override&lt;/span&gt; 

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Runnable&lt;/span&gt; &lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; 

&lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 

&lt;span class="o"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will initialize a KafkaConsumer, which reads and deserializes messages from the &lt;code&gt;test-schema-car-protobuf&lt;/code&gt; topic and displays them in the logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Use Protobuf in Your Pipeline
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Protobuf messages are efficient for high-volume, high-throughput scenarios where messages follow a schema with very few optional attributes and variances in the fields.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the messages are machine-to-machine, and the components in the pipeline are capable of serialization or deserialization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If there are schemas enforced on the data and evolve with a clear forward/backward pattern&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When Not to Use Protobuf in Your Pipeline
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If the data needs to be viewed by humans immediately, with no extra computing overhead, then use a normal String format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the data doesn’t really follow any schemas and can change on an ad-hoc basis, all advantages of Protobuf are negated, and complexity increases unnecessarily.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Protobuf isn’t suitable for applications that require continuous streaming, like file data, videos, etc., as each message is meant to be processed as a whole record.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  GitHub Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/harishva23/GenericProducer" rel="noopener noreferrer"&gt;Generic Producer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/harishva23/GenericConsumer" rel="noopener noreferrer"&gt;Generic Consumer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://docs.confluent.io/kafka/overview.html" rel="noopener noreferrer"&gt;Confluent Kafka Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.confluent.io/platform/current/schema-registry/index.html" rel="noopener noreferrer"&gt;Confluent Schema Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Aiven-Open/karapace" rel="noopener noreferrer"&gt;Aiven Karapace&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kafka.apache.org/41/getting-started/introduction/" rel="noopener noreferrer"&gt;Apache Kafka Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://javadoc.io/doc/org.apache.kafka/kafka-clients/latest/index.html" rel="noopener noreferrer"&gt;Apache Kafka Clients Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://protobuf.dev/overview/" rel="noopener noreferrer"&gt;Protobuf Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For production teams, managing Karapace alongside Kafka brokers, connectors, and stream processors adds significant operational overhead, one of the core reasons teams move to fully managed streaming platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions (FAQs)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Why does adding Schema Registry make Kafka harder to operate? &lt;br&gt;
Schema Registry is a separate component that producers and consumers must talk to for serialization and compatibility. You need to set up, secure, monitor, and upgrade it alongside Kafka brokers, which adds operational overhead and complexity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How does Condense simplify Kafka + Schema Registry? &lt;br&gt;
Condense bundles Kafka-native streaming with integrated Schema Registry (Karapace-compatible), ACLs, and observability in one managed platform. You deploy from cloud marketplaces and get schema governance without running a separate registry node.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What subject naming strategies does Condense support? &lt;br&gt;
Condense supports the standard Confluent naming strategies: TopicNameStrategy, RecordNameStrategy, and TopicRecordNameStrategy. These determine how subjects are named and how schema versions are managed for keys and values.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why is Protobuf better than JSON for high-throughput Kafka pipelines? Protobuf uses compiled classes and binary serialization, which is faster and smaller than JSON's text-based format. This reduces deserialization overhead and consumer lag, especially with nested structures or high data rates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How does Condense help teams ship Protobuf-based streaming pipelines faster? &lt;br&gt;
Condense provides prebuilt connectors, a Git-enabled IDE, and no-code/low-code builders for stream logic, so you can focus on Protobuf message design instead of cluster ops. You get Kafka-native performance with reduced setup time and operational burden.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>dataengineering</category>
      <category>apachekafkaschema</category>
      <category>karapace</category>
      <category>protobuf</category>
    </item>
    <item>
      <title>Kafka Streams 101: A Developer’s Guide to Real-Time Application Logic</title>
      <dc:creator>Sachin Kamath</dc:creator>
      <pubDate>Tue, 16 Jun 2026 10:06:59 +0000</pubDate>
      <link>https://dev.to/zeliotofficial/kafka-streams-101-a-developers-guide-to-real-time-application-logic-2knc</link>
      <guid>https://dev.to/zeliotofficial/kafka-streams-101-a-developers-guide-to-real-time-application-logic-2knc</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Kafka Streams enables real-time stream processing inside applications using local state backed by Kafka logs. However, deploying and managing multiple Kafka Streams microservices at scale is complex, requiring custom CI/CD, state recovery, and observability tooling.&lt;/p&gt;

&lt;p&gt;Condense simplifies this by providing a fully managed, unified streaming platform inside your cloud (BYOC). It integrates Kafka Streams with built-in IDE, Git versioning, prebuilt domain logic, and native observability, eliminating operational overhead while accelerating development and scaling real-time apps reliably.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Apache Kafka has long been a cornerstone of modern data infrastructure, providing a distributed, fault-tolerant backbone for event ingestion at scale. But ingestion is only half the equation. Business value lies in what happens after events are received, how raw data is filtered, joined, aggregated, enriched, and ultimately transformed into decisions.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;This is where Kafka Streams comes in. As a native stream processing library built on Kafka itself, Kafka Streams enables developers to write real-time logic using a simple yet powerful programming model. This blog walks through the foundations of Kafka Streams, explores how it powers real-world applications, and examines the architectural implications for engineering teams. At the end, we’ll also see how modern platforms are simplifying this journey further by eliminating unnecessary complexity from the development lifecycle.&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Kafka Streams Programming Model&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Kafka Streams is fundamentally a Java library that allows developers to treat Kafka topics not just as message queues, but as unbounded data tables or continuously updating datasets. Its core abstractions include:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;KStream: A continuous stream of records. Think of this as the raw event log.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;KTable: A changelog stream that represents the latest value for each key, essentially a materialized view.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;GlobalKTable: A read-only table replicated on each instance, often used for joining reference data.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stream logic is expressed using the Streams DSL or the Processor API. Most applications use the DSL to define transformations &lt;code&gt;like map()&lt;/code&gt;, &lt;code&gt;filter()&lt;/code&gt;, &lt;code&gt;join()&lt;/code&gt;, and &lt;code&gt;aggregate()&lt;/code&gt;, while the Processor API gives lower-level control over state and custom operators.&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  Stateful Processing and Local Stores&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;One of Kafka Streams’ defining features is its local state management. Stateful operations, like &lt;code&gt;groupByKey()&lt;/code&gt;&lt;code&gt;.windowedBy()&lt;/code&gt;&lt;code&gt;.aggregate()&lt;/code&gt;, require storing intermediate state. Instead of centralizing this in a database, Kafka Streams maintains RocksDB-based state stores on the local disk of each processing instance.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;This state is backed by a changelog topic in Kafka. If a failure occurs, the processor recovers by replaying the changelog. This design allows for scalable, distributed stream processing, but it also introduces critical operational requirements:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Persistent disk access for RocksDB.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Monitoring of state restoration and checkpointing.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Partitioned processing tied to Kafka topic partitioning.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-World Application Deployment: Microservices and Beyond&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;In most enterprises, Kafka Streams applications are deployed as microservices. Each stream processing unit, fraud detection, ETA computation, SLA tracking is packaged as a Spring Boot or Quarkus application, then deployed into Kubernetes or another container orchestrator.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;This approach introduces certain responsibilities per service:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintain a complete lifecycle (build, deploy, monitor, patch).&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Handle schema compatibility between topics and application code.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Implement backpressure handling, logging, and metrics.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Define partitioning logic that matches Kafka topic partitioning.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This model is manageable at small scale, but quickly becomes burdensome as the number of real-time applications grows. Teams often end up building:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom CI/CD tooling for streaming services.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;State migration routines for schema evolution.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Monitoring layers to track per-operator lag, backpressure, and failures.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Homegrown governance to version and deploy transforms safely.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The reality is that while Kafka Streams simplifies the programming model, it does not eliminate operational complexity. Most Kafka Streams microservices still need to be treated like full-fledged backend services, each with infrastructure, observability, and deployment overhead.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Managing Failures and Stateful Recovery&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Stateful stream processing introduces unique challenges not seen in stateless services:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Processor crashes require replaying changelogs to restore state.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Version upgrades must avoid state corruption or key mismatch.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Hot deployments risk double processing or record duplication if not orchestrated carefully.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Event time processing with out-of-order data requires complex watermarking and windowing strategies.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kafka Streams supports exactly-once semantics (EOS) with idempotent producers and transactional writes, but this adds additional configuration burden and requires careful coordination between input/output topics and processing guarantees.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;In practice, engineering teams often need to build custom scaffolding to make these patterns reliable, transform state inspection, window replay, timestamp alignment, and state migration versioning.&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Observability Remains an Under-Addressed Challenge&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;While Kafka itself provides metrics on broker health and topic lag, Kafka Streams applications demand pipeline-aware observability:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is a specific stream join introducing backpressure?&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Are certain partitions processing slower due to skewed keys?&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Is the state store nearing disk exhaustion?&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Which application version is currently deployed and processing which partitions?&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;These questions often require setting up Prometheus exporters, embedding Micrometer, and integrating with tools like Grafana, Jaeger, or OpenTelemetry. In many cases, visibility across multi-stage pipelines (e.g., “raw event → session builder → score assigner → alert emitter”) is fragmented and hard to debug during incident response.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  CI/CD and Versioned Transform Pipelines&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Deploying changes to streaming logic requires particular discipline:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stateful operators must be deployed carefully to avoid dropping or reprocessing records.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Version control is critical, not just for source code, but for schemas and processing topology.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Teams must implement rollback strategies for failed deployments without corrupting stream state.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Developers often struggle to test stream topologies locally, especially when logic is embedded deep inside a containerized microservice.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;While Kafka Streams supports topology versioning and testing via TopologyTestDriver, there’s no built-in support for seamless, multi-version CI/CD integration.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What This Means for Real-Time Engineering Teams&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;By now, the picture is clear: Kafka Streams provides the primitives, but not the platform. To make real-time work in production, teams must shoulder:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lifecycle management of dozens of services.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;CI/CD pipelines that are stream-aware.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Governance across schemas, state, and partitioning.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Ops playbooks for fault tolerance, state recovery, and lag monitoring.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;A documentation trail so that new engineers can maintain existing stream logic safely.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;This fragmentation can be a major blocker, not because the underlying code is difficult, but because the integration burden scales with every new pipeline.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How Platforms Like Condense Change the Equation&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Modern real-time platforms are increasingly collapsing this complexity.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Condense, for example, retains Kafka Streams’ power while eliminating the need for separate microservices per application. Instead of building, deploying, and observing independent logic units:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developers write Kafka Streams-style logic inside an integrated IDE, with support for no-code and low-code operators (merge, delay, alert, window).&amp;nbsp;&lt;/li&gt;
&lt;li&gt;All transforms are version-controlled and Git-integrated, enabling safe rollouts, rollbacks, and collaborative development.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;The platform handles orchestration, state recovery, partition scaling, and observability as first-class features.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Prebuilt domain-specific operators (e.g., CAN decoder, trip builder, geofence engine) reduce redundant engineering effort.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;All Kafka brokers and processors run inside the customer’s cloud account via BYOC, ensuring data sovereignty without operational burden.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;By removing the need to wrap each stream job in its own microservice, Condense makes it feasible to scale from 5 to 50+ real-time workflows without growing operational debt linearly.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Closing Thoughts&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Kafka Streams remains a powerful tool in the real-time developer’s toolkit. But making it work at scale involves far more than just calling &lt;code&gt;stream.map()&lt;/code&gt;&lt;code&gt;.filter()&lt;/code&gt;&lt;code&gt;.join()&lt;/code&gt;, it demands operational rigor, architectural forethought, and careful coordination across the development lifecycle.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;For organizations moving from raw events to real-time decisions, the choice is not just about code, it’s about platform strategy.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;As real-time becomes core infrastructure, platforms like Condense that provide an integrated, streaming-native runtime, from ingestion to logic to deployment are proving to be not just convenient, but essential.&amp;nbsp;&lt;/p&gt;

</description>
      <category>kafkastreams</category>
      <category>kafka</category>
      <category>eventdriven</category>
      <category>datastreaming</category>
    </item>
    <item>
      <title>Challenges in Updating Managed Kafka Platforms to Kafka 4.3.0</title>
      <dc:creator>Sachin Kamath</dc:creator>
      <pubDate>Wed, 03 Jun 2026 17:28:05 +0000</pubDate>
      <link>https://dev.to/zeliotofficial/challenges-in-updating-managed-kafka-platforms-to-kafka-430-g0i</link>
      <guid>https://dev.to/zeliotofficial/challenges-in-updating-managed-kafka-platforms-to-kafka-430-g0i</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Updating managed Kafka platforms to Kafka 4.3.0 is not a simple version upgrade. The removal of ZooKeeper, KRaft migration requirements, infrastructure validation, compatibility testing, recovery optimization, and operational changes introduces significant engineering effort for managed Kafka providers. Condense simplifies this complexity by handling Kafka upgrades, infrastructure management, monitoring, scaling, and operational workflows centrally.&lt;/p&gt;

&lt;p&gt;Apache Kafka 4.3.0 introduces major architectural and operational changes across KRaft, storage recovery, consumer coordination, security, and observability. While these improvements strengthen Kafka for production-scale environments, upgrading managed Kafka platforms to Kafka 4.3.0 requires significant engineering effort.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;For managed Kafka providers, upgrades are not limited to changing broker versions. Every infrastructure layer, operational workflow, monitoring pipeline, client compatibility model, and recovery mechanism must be validated carefully before production rollout.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;The move to KRaft-only architecture in Kafka 4.3.0 increases this complexity further because ZooKeeper support is completely removed.&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  Managed Kafka providers must ensure:&amp;nbsp;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cluster stability&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Data safety&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Upgrade compatibility&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Operational continuity&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Multi-tenant reliability&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Security consistency&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Zero or minimal downtime&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;These requirements make Kafka version upgrades operationally intensive.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  KRaft Migration Complexity&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;One of the biggest changes in Kafka 4.3.0 is the complete removal of ZooKeeper support. Kafka clusters now operate entirely on KRaft mode.&amp;nbsp;For managed Kafka providers, this is not simply a configuration update.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Efforts Involved:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Migrating existing ZooKeeper-based clusters&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Validating metadata consistency&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Updating controller management workflows&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Reworking infrastructure automation&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Rebuilding deployment pipelines&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Updating monitoring systems for KRaft&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Providers must validate that KRaft behaves consistently across:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small clusters&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Large multi-tenant environments&amp;nbsp;&lt;/li&gt;
&lt;li&gt;High-throughput workloads&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Disaster recovery scenarios&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Migration errors at the metadata layer can directly impact cluster availability and operational stability.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Infrastructure Validation and Compatibility Testing&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Managed Kafka environments support multiple customer workloads with different:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kafka clients&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Consumer patterns&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Security configurations&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Connector ecosystems&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Streaming applications&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Upgrading Kafka versions requires extensive compatibility validation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Major Efforts Involved&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client compatibility testing&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Connector validation&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Schema registry testing&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Security integration validation&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Consumer group behavior testing&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Kafka Streams compatibility verification&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Providers cannot assume every customer application will behave identically after upgrades&lt;/p&gt;

&lt;p&gt;Even small protocol-level changes can impact:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rebalance behavior&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Throughput patterns&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Latency&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Connector operations&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Stream processing workflows&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes pre-production validation extremely important.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Operational Risk During Upgrades&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Managed Kafka providers operate production-critical environments where downtime risks must remain minimal.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Kafka upgrades require careful operational planning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Efforts Involved&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rolling upgrade orchestration&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Replica synchronization validation&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Partition reassignment handling&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Traffic balancing&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Recovery workflow testing&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Rollback strategy preparation&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Upgrades become even more sensitive in:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High-throughput environments&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Multi-region clusters&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Tiered storage deployments&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Mission-critical systems&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Any instability during upgrades can impact production data pipelines directly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Tiered Storage Recovery Validation&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Kafka 4.3.0 introduces improvements for tiered storage replica recovery.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;While these improvements provide operational advantages, managed Kafka providers must validate recovery behavior thoroughly before enabling them at scale.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Efforts Involved&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recovery testing across large datasets&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Remote storage validation&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Replica synchronization benchmarking&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Failure scenario simulation&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Recovery performance tuning&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tiered storage environments usually operate with massive historical data volumes. Recovery inefficiencies can increase operational overhead significantly if not validated properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Consumer Group Coordination Changes&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Kafka 4.3.0 improves consumer group assignment handling through assignment batching and configurable assignment intervals.&lt;/p&gt;

&lt;p&gt;For managed Kafka providers, consumer group behavior is extremely sensitive because customers operate different scaling models and workload patterns.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Efforts Involved&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rebalance behavior validation&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Autoscaling compatibility testing&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Coordinator load benchmarking&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Consumer lag analysis&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Throughput stability testing&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Even improvements intended to optimize coordination must be validated carefully across different workload patterns before broad rollout.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Monitoring and Observability Updates&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Kafka 4.3.0 introduces new operational metrics and observability improvements, including retention headroom metrics.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Managed Kafka platforms usually maintain centralized observability systems for:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Metrics&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Alerts&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Dashboards&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Capacity planning&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Operational analytics&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every Kafka release requires updates to these monitoring systems.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Efforts Involved&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Updating monitoring pipelines&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Creating new dashboards&lt;/li&gt;
&lt;li&gt;Alert validation&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Storage visibility integration&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Operational analytics updates&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Without proper monitoring updates, new Kafka capabilities cannot be utilized effectively.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Security and IAM Integration Validation&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Kafka 4.3.0 introduces OAuth client assertion support for enterprise authentication workflows.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Managed Kafka providers supporting enterprise customers must validate:&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IAM integrations&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Token-based authentication flows&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Access control behavior&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Security policy compatibility&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Authentication performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Major Efforts Involved&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identity provider testing&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Security workflow validation&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Multi-tenant access verification&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Compliance testing&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Zero-trust architecture validation&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Security upgrades require careful validation because authentication inconsistencies directly affect customer workloads.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Upgrade Coordination Across Multi-Tenant Environments&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;Managed Kafka platforms usually host multiple customer environments on shared infrastructure layers.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;This creates additional operational complexity during upgrades.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Efforts Involved&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tenant-aware rollout planning&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Cluster isolation validation&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Workload impact analysis&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Upgrade scheduling coordination&amp;nbsp;&lt;/li&gt;
&lt;li&gt;SLA management&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Providers must ensure upgrades do not create cascading impact across customer environments.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;This becomes significantly more complex at scale.&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  Engineering Effort Behind Kafka Upgrades&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;From the outside, Kafka upgrades may appear straightforward.&lt;/p&gt;

&lt;p&gt;Internally, managed Kafka providers must coordinate across:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Platform engineering teams&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Infrastructure teams&amp;nbsp;&lt;/li&gt;
&lt;li&gt;SRE teams&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Security teams&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Support teams&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Customer operations teams&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Kafka Upgrades Involve:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure automation updates&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Recovery validation&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Observability changes&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Operational testing&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Security integration updates&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Documentation and support readiness&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The engineering effort behind production-grade Kafka upgrades is substantial.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How Condense Simplifies Kafka Upgrades&amp;nbsp;
&lt;/h2&gt;

&lt;p&gt;At Condense, Kafka infrastructure management, upgrades, scaling, observability, and operational workflows are centrally managed as part of the platform.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Condense simplifies Kafka version adoption by handling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kafka cluster management&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Upgrade orchestration&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Infrastructure automation&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Monitoring and observability&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Security integration&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Scaling workflows&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Recovery operations&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Operational maintenance&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows organizations to adopt newer Kafka versions such as Kafka 4.3.0 without managing the operational complexity internally.&amp;nbsp;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As Kafka evolves with architectural changes like KRaft, tiered storage optimization, and operational improvements, Condense ensures these capabilities are integrated and operationalized efficiently within production environments.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions (FAQs)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Why is KRaft migration a major challenge?&lt;br&gt;
KRaft completely removes ZooKeeper dependency, requiring metadata migration, infrastructure changes, monitoring updates, and operational workflow redesign.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does Kafka 4.3.0 improve operational efficiency?&lt;br&gt;
Yes. Kafka 4.3.0 improves recovery behavior, consumer coordination, observability, security integration, and infrastructure simplification through KRaft architecture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How does Condense simplify Kafka 4.3.0 adoption?&lt;br&gt;
Condense is already built on KRaft-based Kafka architecture, enabling organizations to adopt Kafka 4.3.0 capabilities without handling underlying infrastructure transitions, upgrade orchestration, monitoring, scaling, or operational maintenance internally.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can Condense help organizations adopt Kafka 4.3.0 faster?&lt;br&gt;
Yes. Since Condense already operates on modern Kafka architecture principles including KRaft, organizations can leverage Kafka 4.3.0 operational improvements such as simplified metadata management, recovery optimizations, and enhanced observability without redesigning their Kafka infrastructure stack.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why is KRaft adoption easier with Condense?&lt;br&gt;
KRaft migration usually requires infrastructure redesign, operational workflow changes, metadata management updates, and monitoring modifications. With Condense, these infrastructure complexities are abstracted through a managed streaming platform already aligned with modern Kafka operational architecture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What operational improvements does Kafka 4.3.0 bring to real-time streaming platforms?&lt;br&gt;
Kafka 4.3.0 improves operational efficiency through faster tiered storage recovery, broker cordoning, retention headroom metrics, improved consumer group coordination, and better enterprise security integration. These improvements help organizations run large-scale streaming environments more efficiently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What should organizations consider before upgrading to Kafka 4.3.0?&lt;br&gt;
Organizations should evaluate client compatibility, recovery workflows, monitoring updates, consumer group behavior, connector validation, and operational readiness before upgrading to Kafka 4.3.0. Production rollout should always include staging validation and rollback planning.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does Kafka 4.3.0 require infrastructure changes?&lt;br&gt;
Yes. Kafka 4.3.0 introduces architectural and operational changes that may require updates to deployment workflows, monitoring systems, maintenance processes, and infrastructure automation depending on the existing Kafka environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How does Kafka 4.3.0 improve Kafka maintenance workflows?&lt;br&gt;
Kafka 4.3.0 introduces broker and log directory cordoning, allowing operators to stop new partition assignments during maintenance operations. This simplifies hardware replacement, broker migration, and infrastructure maintenance workflows.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is Kafka 4.3.0 better for large-scale streaming workloads?&lt;br&gt;
Yes. Kafka 4.3.0 improves recovery efficiency, consumer coordination, observability, and operational stability, making it more suitable for large-scale real-time streaming environments with high throughput and large storage volumes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>architecture</category>
      <category>devops</category>
      <category>distributedsystems</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Real-Time Data Streaming vs Batch Data ETL: Why Timing Matters</title>
      <dc:creator>Sachin Kamath</dc:creator>
      <pubDate>Tue, 02 Jun 2026 02:26:41 +0000</pubDate>
      <link>https://dev.to/zeliotofficial/real-time-data-streaming-vs-batch-data-etl-why-timing-matters-1d4m</link>
      <guid>https://dev.to/zeliotofficial/real-time-data-streaming-vs-batch-data-etl-why-timing-matters-1d4m</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Batch ETL moves and processes data on a schedule, delivering insights with built-in latency, ideal for historical analysis and compliance, but ineffective for urgent, real-time business actions. Real-Time Streaming pipelines process each event instantly, enabling on-the-fly fraud detection, predictive maintenance, and hyper-personalized engagement. Timing isn’t just a throughput metric; it determines whether data delivers competitive value or is just hindsight. Condense makes real-time streaming practical and production-ready, letting enterprises turn events into actions within their own cloud, while traditional batch workflows remain valuable for long-term reporting and analytics.&lt;/p&gt;

&lt;p&gt;For decades, batch ETL defined how enterprises integrated and analyzed data. Jobs were scheduled, data was extracted from sources, transformed into a unified schema, and loaded into warehouses or lakes for reporting. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This was enough when businesses primarily asked: what happened yesterday? &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But the operational environment has changed. Industries now compete on the ability to respond instantly whether blocking fraud at the moment of authorization, detecting anomalies in connected fleets, or personalizing customer engagement as interactions unfold. In this landscape,  Real-Time Data Streaming and modern streaming pipelines are not optimizations. They are requirements. &lt;/p&gt;

&lt;p&gt;This blog examines the technical differences between batch ETL and  Real-Time streaming, explains why timing is more than a performance metric, and explores how streaming pipelines are reshaping enterprise architectures. &lt;/p&gt;

&lt;h2&gt;
  
  
  Batch ETL: Strengths and Boundaries
&lt;/h2&gt;

&lt;p&gt;Batch ETL (Extract, Transform, Load) pipelines move data in discrete intervals. They typically operate as follows: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Extract&lt;br&gt;
Pull records from transactional systems, APIs, or files. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Transform&lt;br&gt;
Apply schema normalization, deduplication, or business logic in staging. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Load&lt;br&gt;
Insert processed batches into a target system (warehouse or data lake). &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Technical strengths&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Throughput: Bulk processing of millions of records is efficient on modern compute clusters. &lt;/li&gt;
&lt;li&gt;Determinism: Fixed jobs are easier to validate and audit, making them suitable for compliance. &lt;/li&gt;
&lt;li&gt;Maturity: Tooling (Informatica, Talend, dbt, Airflow) is well established and battle-tested. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Limitations inherent to the design&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Latency: The time between data generation and availability is at least the batch interval minutes, hours, or days. &lt;/li&gt;
&lt;li&gt;Operational blind spots: Events between runs remain invisible. Failures may not be discovered until the next batch completes. &lt;/li&gt;
&lt;li&gt;Rigid scheduling: Workflows are brittle under changing workloads. Rescheduling impacts dependencies downstream. &lt;/li&gt;
&lt;li&gt;Resource spikes: Large jobs create uneven load, with clusters often over provisioned to handle peak windows. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Batch ETL is indispensable for historical analysis and compliance reporting, but unsuitable when insights must drive immediate operational action. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Real-Time Data Streaming: A Continuous Model
&lt;/h2&gt;

&lt;p&gt;Real-Time Data Streaming inverts this paradigm. Instead of moving data in scheduled intervals, every event is treated as a discrete, time ordered signal that can be processed immediately. Kafka and similar log based systems provide the backbone for this architecture. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core mechanics of streaming pipelines:&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Immutable logs: Events are appended to partitions, guaranteeing order and durability. &lt;/li&gt;
&lt;li&gt;Replayability: Consumers can reprocess events from any offset, enabling recovery and backfills. &lt;/li&gt;
&lt;li&gt;Stateful stream processing: Operators maintain state across windows, joins, and aggregations (e.g., “total purchases by customer in the last 5 minutes”). &lt;/li&gt;
&lt;li&gt;Continuous enrichment: Streams are augmented with contextual data (e.g., geolocation, device metadata) in motion. &lt;/li&gt;
&lt;li&gt;Low-latency sinks: Events are delivered to APIs, dashboards, or control systems within milliseconds to seconds. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;This model does not merely accelerate batch. It enables workflows that batch cannot support because the business outcome depends on acting while the event is still unfolding. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why Timing Is Strategic
&lt;/h2&gt;

&lt;p&gt;Timing is not a secondary concern; it directly determines the value of data. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fraud detection: A fraudulent card transaction must be flagged before the authorization completes. A nightly batch report identifies fraud after the funds are gone. &lt;/li&gt;
&lt;li&gt;Predictive maintenance: An abnormal vibration detected mid route can prevent breakdown. Batch ETL will surface it only after the vehicle is already sidelined. &lt;/li&gt;
&lt;li&gt;Customer personalization: Recommending a product while a customer is browsing drives conversion. A next day email is often irrelevant. &lt;/li&gt;
&lt;li&gt;Logistics visibility: A delayed shipment must trigger re routing in the moment. Reporting it after delivery deadlines have passed is operationally useless. &lt;/li&gt;
&lt;li&gt;Cybersecurity: Intrusion attempts must be analyzed in flight to prevent compromise. Batch ETL provides forensic evidence, not active defense. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;In each case, the same data is processed. The difference is timing. Batch delivers hindsight. Streaming delivers foresight. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Demand for Streaming Pipelines
&lt;/h2&gt;

&lt;p&gt;Enterprises are increasingly building streaming pipelines because the nature of their industries leaves no tolerance for latency. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Financial services:  Real-Time AML checks, fraud detection, and instant payment processing are both competitive and regulatory mandates. &lt;/li&gt;
&lt;li&gt;Mobility and automotive: Vehicles generate telemetry that must be analyzed continuously for safety and efficiency. &lt;/li&gt;
&lt;li&gt;Telecom and IoT: Billions of device signals require filtering, aggregation, and anomaly detection at scale. &lt;/li&gt;
&lt;li&gt;Retail and digital platforms: Context aware personalization drives customer engagement. Delayed data undermines the business model. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The demand side is clear: data is only valuable if it can be acted upon within the time window that matters. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Coexistence: Batch and Streaming Together
&lt;/h2&gt;

&lt;p&gt;This is not a zero sum choice. Batch ETL and streaming coexist in most enterprises: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Batch ETL: Best for historical analytics, compliance archiving, financial reporting, and periodic aggregations. &lt;/li&gt;
&lt;li&gt;Real-Time Data Streaming: Best for operational intelligence, anomaly detection, personalization, SLA monitoring, and IoT telemetry. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The shift is not about replacement, but about recognizing that streaming pipelines increasingly occupy the critical front line of enterprise decision making. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why Real Time Data Streaming Platforms like Condense Matters Here
&lt;/h2&gt;

&lt;p&gt;This is where &lt;a href="https://www.zeliot.in/condense" rel="noopener noreferrer"&gt;Condense&lt;/a&gt; makes a difference. It is a Kafka Native platform designed to deliver production-ready streaming pipelines inside the enterprise’s own cloud environment (BYOC). With &lt;a href="https://www.zeliot.in/condense" rel="noopener noreferrer"&gt;Condense&lt;/a&gt;, organizations don’t just get Managed Kafka brokers they get a complete runtime that manages ingestion, stream processing, stateful recovery, observability, and domain-specific transforms. &lt;/p&gt;

&lt;p&gt;That means enterprises can move from raw events to actionable insights in minutes, without taking on the operational weight of building pipelines from scratch. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Batch ETL will remain valuable, but the competitive edge lies in  Real-Time. Condense enables enterprises to capture that edge by making  Real-Time Data Streaming both practical and production-ready. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions (FAQs)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What is the main difference between batch ETL and Real-Time Data Streaming?&amp;nbsp;&lt;br&gt;
Batch ETL processes data in scheduled intervals, while Real-Time Data Streaming processes each event as it happens.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why are streaming pipelines faster than batch ETL?&amp;nbsp;&lt;br&gt;
Streaming pipelines handle events continuously with low latency, unlike batch jobs that wait for scheduled runs.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When should enterprises use batch ETL instead of streaming?&amp;nbsp;&lt;br&gt;
Batch ETL is best for historical reporting, compliance archives, and workloads where timing is not critical.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why is timing important in Real-Time Data Streaming?&amp;nbsp;&lt;br&gt;
Timing ensures events drive immediate actions, such as fraud blocking, predictive maintenance, or real-time personalization.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can batch ETL and streaming pipelines coexist?&amp;nbsp;&lt;br&gt;
Yes, most enterprises use streaming pipelines for live operations and batch ETL for long-term analytics.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What industries benefit most from Real-Time Data Streaming?&amp;nbsp;&lt;br&gt;
Finance, mobility, logistics, IoT, and retail depend on Real-Time Data Streaming for mission-critical decisions.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How does Condense improve the adoption of streaming pipelines?&amp;nbsp;&lt;br&gt;
&lt;a href="https://www.zeliot.in/condense" rel="noopener noreferrer"&gt;Condense&lt;/a&gt; is a Kafka Native platform that lets enterprises build production-ready streaming pipelines in minutes inside their own cloud.&amp;nbsp;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>etl</category>
      <category>eventdriven</category>
      <category>kafka</category>
      <category>dataplatform</category>
    </item>
    <item>
      <title>AIDL deep dive post does not exist! Part - I</title>
      <dc:creator>Prasanna</dc:creator>
      <pubDate>Sat, 18 Jul 2020 06:33:30 +0000</pubDate>
      <link>https://dev.to/zeliotofficial/aidl-deep-dive-post-does-not-exist-part-i-4po8</link>
      <guid>https://dev.to/zeliotofficial/aidl-deep-dive-post-does-not-exist-part-i-4po8</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Hello there! I am going to talk about Android's parliamentary conversations. What do I mean by that? I mean, the IPC(Inter Process Communication) that is happening inside Android system. We are going to use AIDL for the so called "conversation". I will explain better and deeper in this article.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;We all know it!&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Why is this a brand new post? Because, it's not about the IPC of components inside one Android application. It's about the communication of two different applications. Most people agree to disagree that it's pretty easy to understand AIDLs. But, there is saying(of mine), &lt;code&gt;"If you understand interfaces in OOP, you shall understand AIDL!"&lt;/code&gt;. Well, Let's see what that saying really means, in detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The AIDL unbolted.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Android Interface Definition Language(AIDL), is what you every time you Google AIDL. This doesn't explain what it really is. Let me explain! AIDL is an Android implementation to achieve Inter Process Communication(IPC) in between Android components. Diving deep, there is a program called &lt;code&gt;aidl&lt;/code&gt;, which compiles the AIDL source code and generates client(Proxy) and server(Stub) Java interfaces.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fprgype5k7uh08zi40kly.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fprgype5k7uh08zi40kly.png" alt="Alt Text" width="675" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Initial building blocks.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let us start with the basics. To create an AIDL, we need to open an Android Project and click &lt;code&gt;File -&amp;gt; New -&amp;gt; AIDL -&amp;gt; AIDL File&lt;/code&gt;. Write your first AIDL file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface IMyAidlInterface {
    String getMessage();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, do not forget to &lt;code&gt;Build -&amp;gt; Rebuild&lt;/code&gt;. The &lt;code&gt;IMyAidlInterface&lt;/code&gt; class will be generated. Create a class which extends the &lt;code&gt;IMyAidlInterface.Stub&lt;/code&gt;. Please remember to override &lt;code&gt;getMessage()&lt;/code&gt; method in this class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class MyImplementor extends IMyAidlInterface.Stub {
    @Override
    public String getMessage() {
        return "Hello from AIDL Stub!";
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we have extended the Stub class and implemented(overridden) the method, we must create a Service which is going to expose the APIs to the applications which need bind the AIDL functionalities.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class MyService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new MyImplementor();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, add the &lt;code&gt;&amp;lt;service&amp;gt;&lt;/code&gt; tag in &lt;code&gt;AndroidManifest.xml&lt;/code&gt; inside &lt;code&gt;&amp;lt;application&amp;gt;&lt;/code&gt; tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;service
    android:name=".MyService"
    android:enabled="true"
    android:exported="true"
    android:process=":remote"&amp;gt;
    &amp;lt;intent-filter&amp;gt;
        &amp;lt;action android:name="MyService" /&amp;gt;
    &amp;lt;/intent-filter&amp;gt;
&amp;lt;/service&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Now that we have implemented the Service part, we should go ahead and create another Android project for the client part. Please note that the AIDLs are very &lt;strong&gt;case-sensitive&lt;/strong&gt;. Unfortunately, Android Studio is not mature enough to detect the syntax errors in an AIDL file. Any changes in an AIDL file would need a rebuild of the project.&lt;br&gt;
&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;The Real River to cross!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We are done with the server(Service) part. Now, we should create another application which will be our client part. So, create a new project in Android Studio. After creating the project, we have to do one of the most important things.&lt;br&gt;
&amp;nbsp;&lt;/p&gt;

&lt;p&gt;In Android Studio, select the Project view in the left top menu. Inside &lt;code&gt;app/src/main/&lt;/code&gt;, create a folder called &lt;code&gt;aidl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcpc4t7zilznasmno0eeh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcpc4t7zilznasmno0eeh.png" alt="Alt Text" width="800" height="321"&gt;&lt;/a&gt;&lt;br&gt;
&amp;nbsp;&lt;/p&gt;

&lt;p&gt;After this, go to the AIDL service application, and copy the contents of &lt;code&gt;aidl&lt;/code&gt; folder.&lt;br&gt;
&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fht0bxlgcj9a6o834a47y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fht0bxlgcj9a6o834a47y.png" alt="aidl2" width="397" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Switch back to the client application and paste the contents into &lt;code&gt;aidl&lt;/code&gt; folder. &lt;code&gt;Build -&amp;gt; Rebuild&lt;/code&gt;. The project should build without any errors.&lt;br&gt;
&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Go to MainActivity.java and create a &lt;code&gt;ServiceConnection&lt;/code&gt; object and &lt;code&gt;IMyAidlInterface&lt;/code&gt; instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private IMyAidlInterface iMyAidlInterface;
private final ServiceConnection mServiceConnection =
    new ServiceConnection() {
        @Override
        public void onServiceConnected(
                    ComponentName name, IBinder service) {

            iMyAidlInterface =
                    IMyAidlInterface.Stub.asInterface(service);

            Log.d(TAG, "Service Connected.");
            Toast.makeText(MainActivity.this, "Service Connected.", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            iMyAidlInterface = null;
            Toast.makeText(MainActivity.this, "Service Disconnected.", Toast.LENGTH_SHORT).show();
        }
    };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;onCreate()&lt;/code&gt; of &lt;code&gt;MainActivity.java&lt;/code&gt;, bind the service. Note that we need the action and the package name to successfully bind to the service.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Intent intent = new Intent();
    intent.setPackage("com.zeliot.aidldemo");
    intent.setAction("MyService");
    bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, create a button and while clicking the button, call &lt;code&gt;iMyAidlInterface.getMessage()&lt;/code&gt; to receive the String from the AIDL service.&lt;br&gt;
&amp;nbsp;&lt;/p&gt;

&lt;p&gt;We are done with client and server parts. As of now, the Service is connected from another application. We can do any type of operations using the same. We can have data trasnfer,aynchronous calls, callbacks. More detailed implementation will be released in the second part of this series.&lt;br&gt;
&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/prasan29/aidl-blog" rel="noopener noreferrer"&gt;AIDL source code&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
&amp;nbsp;&lt;/p&gt;

&lt;h2&gt;
  
  
  Thank you, for reading. Happy interfacing!! 😀 🙂
&lt;/h2&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fprofile-counter.glitch.me%2Fprasan29%2Fcount.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fprofile-counter.glitch.me%2Fprasan29%2Fcount.svg" alt="Visits" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>aidl</category>
      <category>java</category>
      <category>kotlin</category>
    </item>
  </channel>
</rss>
