Kafka-node
TypeScript
Programming
Software Development
Node.js

How to use kafka-node under typescript?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Using kafka-node from TypeScript is mostly about getting three pieces right: the package install, the type declarations, and the event-driven producer or consumer code. The library works with TypeScript, but it is an older Kafka client, so it helps to write your wrappers carefully instead of treating the callback-heavy API as if it were fully modern and promise-based.

Install The Package And Types

bash
npm install kafka-node
npm install --save-dev @types/kafka-node typescript

If your project does not already have a TypeScript config, initialize one.

bash
npx tsc --init

A simple tsconfig.json for Node.js work usually needs CommonJS or a compatible module target, depending on how the rest of the application is built.

Creating A Kafka Client And Producer

typescript
1import * as kafka from "kafka-node";
2
3const client = new kafka.KafkaClient({
4  kafkaHost: "localhost:9092",
5});
6
7const producer = new kafka.Producer(client);
8
9producer.on("ready", () => {
10  const payloads: kafka.ProduceRequest[] = [
11    { topic: "demo-topic", messages: ["hello from typescript"] },
12  ];
13
14  producer.send(payloads, (err, data) => {
15    if (err) {
16      console.error("send failed", err);
17      return;
18    }
19    console.log("send result", data);
20  });
21});
22
23producer.on("error", (err) => {
24  console.error("producer error", err);
25});

The ready event matters. Sending before the producer is ready is a common source of confusing failures.

Consuming Messages

typescript
1const consumer = new kafka.Consumer(
2  client,
3  [{ topic: "demo-topic", partition: 0 }],
4  { autoCommit: true }
5);
6
7consumer.on("message", (message) => {
8  console.log("received", message.value);
9});
10
11consumer.on("error", (err) => {
12  console.error("consumer error", err);
13});

This is the basic event-driven consumption model. If you need stronger group-coordination behavior, ConsumerGroup is usually the more relevant API.

Promisifying The Callback API

TypeScript codebases often prefer promises for control flow. You can wrap callback methods yourself.

typescript
1function sendMessage(
2  producer: kafka.Producer,
3  payloads: kafka.ProduceRequest[]
4): Promise<unknown> {
5  return new Promise((resolve, reject) => {
6    producer.send(payloads, (err, data) => {
7      if (err) {
8        reject(err);
9        return;
10      }
11      resolve(data);
12    });
13  });
14}

That keeps the rest of the application cleaner while still using kafka-node underneath.

Topic Metadata And Offsets

If you need topic details, the client exposes metadata-related methods.

typescript
1client.loadMetadataForTopics(["demo-topic"], (err, results) => {
2  if (err) {
3    console.error(err);
4    return;
5  }
6  console.log(results);
7});

This can help during startup validation or diagnostics.

Shutdown Matters

Kafka clients keep sockets open, so graceful shutdown is important.

typescript
1function shutdown() {
2  consumer.close(true, () => {
3    producer.close(() => {
4      client.close(() => process.exit(0));
5    });
6  });
7}
8
9process.on("SIGINT", shutdown);

Without explicit cleanup, Node processes can appear to hang after work is done.

TypeScript Caveats

The type definitions help, but not every runtime behavior is captured perfectly. It is worth wrapping library usage behind a narrow interface if the rest of your codebase expects stronger typing guarantees.

That also makes it easier to migrate later if you choose a different Kafka client.

A Practical Note About kafka-node

kafka-node is older software. It still appears in existing systems, but many teams now prefer newer Kafka clients with stronger TypeScript ergonomics and maintenance. If you are working in an existing codebase, use it carefully. If you are starting fresh, it is reasonable to compare alternatives before committing.

Common Pitfalls

The biggest mistake is producing messages before the ready event fires. Another is assuming the callback API behaves like promises without adding your own wrapper. Developers also often forget to close the consumer and producer, which leaves the process alive. Finally, older Kafka clients can have version-specific quirks with broker features, so do not assume every modern Kafka capability maps cleanly to an older Node client library.

Summary

  • Install both kafka-node and its TypeScript definitions.
  • Wait for producer readiness before sending messages.
  • Consume through event handlers and wrap callbacks when you want promise-style control flow.
  • Close clients explicitly on shutdown.
  • Treat kafka-node as a workable legacy client, but be aware of its age and limitations.

Course illustration
Course illustration

All Rights Reserved.