<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Venu's Blog Post]]></title><description><![CDATA[Venu's Blog Post]]></description><link>https://thelazydev17.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sun, 20 Sep 2026 09:56:12 GMT</lastBuildDate><atom:link href="https://thelazydev17.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Easy Methods for Adding Kafka to Your JS App]]></title><description><![CDATA[Hello! In this article I will be sharing a quick and concise demonstration on how to use Kafka for user analytics, I'll share a small project I developed to track the number of users currently logged in.
This mini app is part of my learning journey. ...]]></description><link>https://thelazydev17.hashnode.dev/easy-methods-for-adding-kafka-to-your-js-app</link><guid isPermaLink="true">https://thelazydev17.hashnode.dev/easy-methods-for-adding-kafka-to-your-js-app</guid><category><![CDATA[kafka]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Redis]]></category><category><![CDATA[Microservices]]></category><dc:creator><![CDATA[Venusai]]></dc:creator><pubDate>Sun, 22 Jun 2025 18:51:37 GMT</pubDate><content:encoded><![CDATA[<p>Hello! In this article I will be sharing a quick and concise demonstration on how to use Kafka for user analytics, I'll share a small project I developed to track the number of users currently logged in.</p>
<p><em>This mini app is part of my learning journey. If you have any suggestions for improving the implementation or design, please let me know, as it can help me enhance my skills.</em></p>
<p>Prerequisite : Basic Knowledge of Kafka. Can refer this <a target="_blank" href="https://youtu.be/QkdkLdMBuL0?si=6jsYGVUNFvUVNCYc">resource</a></p>
<p>You can check out the <a target="_blank" href="https://github.com/Venu005/kakfa-analytics">github repo</a> for source code</p>
<h2 id="heading-technologies-used">Technologies used</h2>
<ul>
<li><p>NodeJS</p>
</li>
<li><p>Express JS</p>
</li>
<li><p>Kafka-js package</p>
</li>
<li><p>Docker</p>
</li>
<li><p>Redis</p>
</li>
<li><p>MongoDB</p>
</li>
</ul>
<h2 id="heading-project-structure">Project structure</h2>
<p>The app is divided into three modules</p>
<ul>
<li><p>Authentication service (contains Kafka producer too)</p>
</li>
<li><p>Kafka Admin</p>
</li>
<li><p>Kafka Consumer</p>
</li>
</ul>
<h2 id="heading-design">Design</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750616187733/99080dd4-9d16-4f42-b8eb-9b2e9f557374.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-implementation">Implementation</h2>
<p>Docker commands for zookeeper and kafka</p>
<pre><code class="lang-bash"> docker run -it -p 2181:2181 zookeeper <span class="hljs-comment">#zookeeper</span>
</code></pre>
<pre><code class="lang-bash"><span class="hljs-comment">#kafka </span>
docker run -p 9092:9092 -e KAFKA_ZOOKEEPER_CONNECT=&lt;your-ip&gt;:2181 -e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://&lt;your-ip&gt;:9092 -e KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1 confluentinc/cp-kafka
</code></pre>
<p>Kafka Admin : The main job of the admin is to create topics and partitions.</p>
<ul>
<li>Initialize a Kafka class and create an admin</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// kafka-admin/index.js</span>
<span class="hljs-keyword">import</span> { Kafka } <span class="hljs-keyword">from</span> <span class="hljs-string">"kafkajs"</span>;

<span class="hljs-keyword">const</span> kafka = <span class="hljs-keyword">new</span> Kafka({
  <span class="hljs-attr">clientId</span>: <span class="hljs-string">"kafka-admin"</span>,
  <span class="hljs-attr">brokers</span>: [<span class="hljs-string">"your-ip:9092"</span>], <span class="hljs-comment">//! add ip address</span>
});

<span class="hljs-keyword">const</span> admin = kafka.admin();

<span class="hljs-keyword">const</span> connectAdmin = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> admin.connect();
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Failed to connect admin: "</span> + error.message);
  }
};
</code></pre>
<ul>
<li><p>A function to create a topic and initialize the kafka admin setup</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> createTopic = <span class="hljs-keyword">async</span> (topicName) =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> admin.createTopics({
        <span class="hljs-attr">topics</span>: [{ <span class="hljs-attr">topic</span>: topicName }],
      });
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Topic <span class="hljs-subst">${topicName}</span> created successfully`</span>);
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Failed to create topic: "</span> + error.message);
    }
  };

  <span class="hljs-keyword">const</span> init = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> connectAdmin();
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Kafka admin connected successfully"</span>);
      <span class="hljs-keyword">await</span> createTopic(<span class="hljs-string">"user-activity"</span>);
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Error initializing Kafka admin:"</span>, error.message);
    } <span class="hljs-keyword">finally</span> {
      <span class="hljs-keyword">await</span> admin.disconnect();
    }
  };

  init()
    .then(<span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Kafka admin initialization complete"</span>);
    })
    .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
      <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Error during Kafka admin initialization:"</span>, error.message);
    });
</code></pre>
</li>
<li><p>Now run the file</p>
<pre><code class="lang-bash">  node index.js
</code></pre>
</li>
</ul>
<p>Kafka Consumer : Consumer groups can consume the topics</p>
<p><strong>Important : Kafka Consumers need to gave groupId</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">//consumer/index.js</span>
<span class="hljs-keyword">import</span> { Kafka } <span class="hljs-keyword">from</span> <span class="hljs-string">"kafkajs"</span>;

<span class="hljs-keyword">const</span> kafka = <span class="hljs-keyword">new</span> Kafka({
  <span class="hljs-attr">clientId</span>: <span class="hljs-string">"consumer-service"</span>,
  <span class="hljs-attr">brokers</span>: [<span class="hljs-string">"your-ip:9092"</span>],
});

<span class="hljs-keyword">const</span> consumer = kafka.consumer({
  <span class="hljs-attr">groupId</span>: <span class="hljs-string">"user-activity-group"</span>,
});
</code></pre>
<ul>
<li>Now the consumer subscribes to the topic ‘user-activity’ and based on the type of event it is stored in redis database</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> run = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> consumer.connect();
    <span class="hljs-keyword">await</span> consumer.subscribe({
      <span class="hljs-attr">topics</span>: [<span class="hljs-string">"user-activity"</span>],
      <span class="hljs-attr">fromBeginning</span>: <span class="hljs-literal">false</span>,
    });
    <span class="hljs-keyword">await</span> consumer.run({
      <span class="hljs-attr">eachMessage</span>: <span class="hljs-keyword">async</span> ({ topic, partition, message }) =&gt; {
        <span class="hljs-keyword">const</span> result = <span class="hljs-built_in">JSON</span>.parse(message.value.toString());
        <span class="hljs-keyword">if</span> (result.eventType === <span class="hljs-string">"user.login"</span>) {
          <span class="hljs-keyword">await</span> redis.sadd(<span class="hljs-string">"active-users"</span>, result.metaData.userId);
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`User <span class="hljs-subst">${result.metaData.email}</span> logged in`</span>);
        }
        <span class="hljs-keyword">if</span> (result.eventType === <span class="hljs-string">"user.logout"</span>) {
          <span class="hljs-keyword">await</span> redis.srem(<span class="hljs-string">"active-users"</span>, result.metaData.userId);
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`User <span class="hljs-subst">${result.metaData.email}</span> logged out`</span>);
        }

        <span class="hljs-keyword">const</span> activeUsersCount = <span class="hljs-keyword">await</span> redis.scard(<span class="hljs-string">"active-users"</span>);
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Active users count: <span class="hljs-subst">${activeUsersCount}</span>`</span>);
      },
    });
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Error in consumer run:"</span>, error);
  }
};
</code></pre>
<ul>
<li>Run the function</li>
</ul>
<pre><code class="lang-javascript">run().catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Failed to run consumer"</span>, error.message);
});
</code></pre>
<p>Kafka Producer: It publishes data (messages) to a Kafka topic.</p>
<ul>
<li><p>Here I wrote a function to send the message after logging in</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">//producer/index.js</span>
  <span class="hljs-keyword">import</span> { Kafka } <span class="hljs-keyword">from</span> <span class="hljs-string">"kafkajs"</span>;

  <span class="hljs-keyword">const</span> kafka = <span class="hljs-keyword">new</span> Kafka({
    <span class="hljs-attr">clientId</span>: <span class="hljs-string">"auth-service"</span>,
    <span class="hljs-attr">brokers</span>: [<span class="hljs-string">"192.168.1.4:9092"</span>],
  });

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> producer = kafka.producer();

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> connectProducer = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> producer.connect();
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Producer connected successfully"</span>);
      <span class="hljs-keyword">return</span> producer;
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Failed to connect producer: "</span> + error.message);
    }
  };

  <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> sendLoginEvent = <span class="hljs-keyword">async</span> (userData) =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> message = {
        <span class="hljs-attr">key</span>: userData.userId,
        <span class="hljs-attr">value</span>: <span class="hljs-built_in">JSON</span>.stringify({
          <span class="hljs-attr">eventType</span>: <span class="hljs-string">"user.login"</span>,
          <span class="hljs-attr">metaData</span>: userData,
        }),
      };
      <span class="hljs-keyword">await</span> producer.send({
        <span class="hljs-attr">topic</span>: <span class="hljs-string">"user-activity"</span>,
        <span class="hljs-attr">messages</span>: [message],
      });
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Login event sent successfully"</span>);
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Failed to send the login event"</span>, error.message);
    }
  };
</code></pre>
<p>  Now the kafka set-up is complete and <code>sendLoginEvent(userData)</code> can be called when logging in</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">await</span> sendLoginEvent({
          <span class="hljs-attr">userId</span>: user._id.toString(),
          <span class="hljs-attr">email</span>: user.email,
          <span class="hljs-attr">userName</span>: user.userName,
          <span class="hljs-attr">loginTime</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toISOString(),
          <span class="hljs-attr">ipAddress</span>: req.ip,
        });
      } <span class="hljs-keyword">catch</span> (kafkaError) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Failed to send login event to Kafka:"</span>, kafkaError.message);
      }
</code></pre>
<p>  Don’t forget to initialize Kafka producer</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> initializeServices = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> connectDB();
      <span class="hljs-keyword">await</span> connectProducer();
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"All services connected successfully"</span>);
      app.listen(<span class="hljs-number">5004</span>, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Auth service is running on port 5004"</span>);
      });
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Failed to initialize services:"</span>, error.message);
      process.exit(<span class="hljs-number">1</span>); <span class="hljs-comment">// Exit if critical services fail</span>
    }
  };

  <span class="hljs-comment">// Initialize all services</span>
  initializeServices();
</code></pre>
</li>
<li><p>Create end points</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">//express js routes</span>
  router.post(<span class="hljs-string">"/login"</span>, login);
</code></pre>
<h3 id="heading-the-logged-in-users-count">The logged-in users count</h3>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750617932899/effbbecc-b85c-4f7a-8e7d-9ced7c59dfd4.png" alt class="image--center mx-auto" /></p>
<p>  So, this was the mini app I built , Please let me know in the comments how can this be improved.</p>
</li>
</ul>
<p><em>Thank you!!!</em></p>
]]></content:encoded></item></channel></rss>