Kafka JavaScript Clients: KafkaJS vs. Platformatic Kafka
KafkaJS has long been a familiar choice for Node.js applications that want a JavaScript API without a native addon. Platformatic Kafka offers a newer pure-JavaScript client with stream-based consumers and support focused on current Node.js releases. confluent-kafka-javascript provides a Promise-based API influenced by KafkaJS and backed by librdkafka, while node-rdkafka remains relevant for applications that use its lower-level native interface.
This guide compares the four clients' Node.js support, native dependencies, consumer processing models, serialization options, Schema Registry support, and migration costs. A separate set of GitHub metrics shows recent maintenance activity and visible public usage.
Quick decision
| Situation | Best starting point | What to verify |
|---|---|---|
| Pure JavaScript, stream-firstPrioritizes active development and modern Node.js streams | Platformatic Kafka | Supports Node.js 22.22+ or 24.6+; its stream-based consumer model fits; experimental Schema Registry integration is acceptable. |
| Pure JavaScript, established APIPrioritizes a longer public track record and older Node.js support | KafkaJS | Its maintenance model and Kafka feature coverage meet your requirements (latest npm release was Feb 2023). |
| librdkafka with a Promise APINeeds Confluent support or a KafkaJS-influenced API | confluent-kafka-javascript | Prebuilt binaries support every target operating system, CPU architecture, Node.js version, and packaging environment. |
| Direct librdkafka integrationNeeds event-driven, callback, or Node.js stream APIs | node-rdkafka | Its lower-level configuration and API provide enough value to prefer it over Confluent's newer Promise client. |
| Migrating from KafkaJSSeeking active maintenance or features unavailable in KafkaJS | confluent-kafka-javascript (closest API)or Platformatic Kafka (pure JavaScript) | Confluent retains eachMessage/eachBatch; Platformatic moves consumer processing to streams. See the Confluent migration guide and Platformatic migration guide. |
Tip: These clients provide Kafka messaging, not stateful stream processing. For windows, joins, or managed state stores, use a dedicated framework such as Apache Flink or Kafka Streams.
Kafka JavaScript clients compared
Versions and capabilities checked against official documentation and npm metadata on 28 Aug 2026.
All four clients also support TLS and mutual TLS.
| Capability | Platformatic Kafka (2.11.0) | KafkaJS (2.2.4) | confluent-kafka-javascript (1.10.0) | node-rdkafka (3.6.1) |
|---|---|---|---|---|
| Runtime | Pure TypeScript/JavaScript; no native addon | Pure JavaScript; no native addon | librdkafka native addon | librdkafka native addon |
| Node.js | 22.22+ or 24.6+ | 14+ | 18+ | 16+ |
| Consumer | Readable streams | eachMessage / eachBatch | eachMessage / eachBatch; callback API | Events, callbacks, streams |
| Authentication | PLAIN, SCRAM, OAUTHBEARER | PLAIN, SCRAM, OAUTHBEARER | PLAIN, SCRAM, OAUTHBEARER, GSSAPI | PLAIN, SCRAM, OAUTHBEARER, GSSAPI |
| Transactions | Idempotence and transactions | Transactions; idempotence experimental | Idempotence and transactions | Idempotence and transactions |
| Schema Registry | Built in (experimental) | Separate KafkaJS package | First-party package | No built-in integration |
Platformatic Kafka
Platformatic Kafka is a pure TypeScript/JavaScript client for current Node.js releases. Its consumer returns a Readable stream, making for await...of, stream composition, and Node.js backpressure part of the consumer design.
Capabilities and limitations
- Kafka and tooling: Version 2.11.0 supports Kafka 3.5 through 4.2, including the KIP-848 consumer group protocol, with implemented features listed in a KIP support matrix. It includes serializers,
bigintoffsets and timestamps, andnode:diagnostics_channelintegration. - Schema Registry: Built-in Avro, Protobuf, and JSON Schema support is experimental and can change outside a major release.
- Deployment constraints: It requires Node.js 22.22+ or 24.6+ and supports PLAIN, SCRAM, and OAUTHBEARER, but not GSSAPI/Kerberos. Consumer streams default to a
highWaterMarkof 1024 messages, which should be reduced for large records. The project also publishes benchmarks that you can use as a reference for your own testing.
When to choose Platformatic Kafka
Choose Platformatic Kafka for a new service that can run on a current Node.js release and needs KIP-848 without a native addon or benefits from stream-based consumption. Choose another client if the deployment requires GSSAPI/Kerberos or stable Schema Registry APIs.
KafkaJS
KafkaJS is a pure JavaScript client with a Promise-based API and eachMessage and eachBatch consumer handlers. It supports older Node.js releases without a native addon.
Capabilities and limitations
- Protocol and authentication: KafkaJS supports producers, transactions, headers, and an Admin client, plus PLAIN, SCRAM, and OAUTHBEARER authentication, but not GSSAPI/Kerberos. Amazon MSK IAM works through AWS's signer package and an OAUTHBEARER token provider. KafkaJS uses classic consumer groups with a built-in round-robin assigner; custom assigners are possible, but KIP-848 and a built-in cooperative-sticky assigner are absent.
- Compression and schemas: GZIP compression is included; Snappy, LZ4, and ZSTD require additional codec packages, and Schema Registry support comes from a separate KafkaJS package. KafkaJS decompresses records but does not expose the original compression codec on consumed messages.
- Release status and Node.js 24: The latest release is version 2.2.4, published in February 2023. On Node.js 24, it can schedule a 1 ms timer loop on idle connections, causing a
TimeoutNegativeWarningand unnecessary CPU use.
When to choose KafkaJS
Keep KafkaJS when an existing application is stable and does not need GSSAPI/Kerberos, a built-in cooperative-sticky assigner, or KIP-848. For a new pure JavaScript service, prefer Platformatic Kafka if its runtime and stream model fit; choose Confluent's client when librdkafka features, first-party Schema Registry support, or commercial support matters.
confluent-kafka-javascript
confluent-kafka-javascript combines librdkafka with a KafkaJS-influenced Promise API. It retains eachMessage and eachBatch and also provides a callback API derived from node-rdkafka.
Capabilities and limitations
- Kafka features: Version 1.10.0 includes librdkafka 2.15.0, so Kafka 4 deployments can use KIP-848. GZIP, Snappy, LZ4, and ZSTD require no additional JavaScript codec packages, and authentication supports GSSAPI/Kerberos in addition to PLAIN, SCRAM, and OAUTHBEARER.
- Packaging and schemas: Confluent publishes prebuilt binaries for supported Linux, macOS, and Windows combinations, while Yarn and pnpm support remain experimental. Unsupported targets may require
node-gypand a C/C++ toolchain. Schema Registry support comes from the first-party@confluentinc/schemaregistrypackage. - KafkaJS compatibility: The compatible layer reduces migration work but does not support custom producer partitioners, custom consumer assigners, or
consumer.stop(), and its Admin API covers only a subset of KafkaJS methods.
When to choose confluent-kafka-javascript
Choose Confluent's client when a new service needs GSSAPI/Kerberos, first-party Schema Registry support, commercial support, or the closest maintained migration path from KafkaJS. Verify binary availability for every development and production target.
node-rdkafka
node-rdkafka exposes librdkafka configuration through event-driven producers and consumers, callbacks, stream helpers, delivery reports, and transactions.
Capabilities and limitations
- Kafka features: Version 3.6.1 includes librdkafka 2.12.0, which supports KIP-848 with Kafka 4 brokers. Authentication follows librdkafka and includes GSSAPI/Kerberos, while the direct configuration surface suits applications that depend on native callbacks and settings.
- Producer and Admin APIs: The standard Producer API must call
poll()or configuresetPollInterval(); otherwise, delivery reports are not emitted and the internal queue can eventually fill. The Admin client creates and deletes topics and increases partition counts but does not expose librdkafka's configuration-alteration APIs. - Deployment: The native addon must be tested on every target. Linux and macOS are the main supported platforms, while Windows support may lag. Confluent's newer client shares this lineage but provides a documented prebuilt-binary support matrix and a Promise-oriented API.
When to choose node-rdkafka
Keep node-rdkafka when an existing application relies on its API or direct librdkafka configuration. For a new service, choose Confluent's client unless the lower-level event or stream interface is a specific requirement.
Migrating from KafkaJS
This guide covers two practical migration paths for KafkaJS applications. confluent-kafka-javascript retains much of the KafkaJS API and usually requires fewer application changes, but it introduces a native addon. Platformatic Kafka has no native addon, but consumer processing must be rewritten around Node.js streams.
Amazon MSK IAM: KafkaJS uses an external AWS signer through OAUTHBEARER. Before migrating, verify the target client's token-provider and token-refresh integration.
Migrating from KafkaJS to Platformatic Kafka
Platformatic provides a detailed KafkaJS migration guide. The migration changes both APIs and application behavior.
| Area | KafkaJS | Platformatic Kafka | Migration impact |
|---|---|---|---|
| Client & config | Shared new Kafka() factory | Direct Producer, Consumer, and Admin clients | Separate configs; rename brokers to bootstrapBrokers; flatten retries; uppercase SASL values. |
| Connections | Explicit connect() / disconnect() | Lazy connect; explicit close() | Remove startup connects; close clients during shutdown. |
| Producing | Topic on send(); separate sendBatch() | Topic per message; one send() | Move topic into messages; pass compression as a string. |
| Consumption & commits | subscribe() + run(); commitOffsets() | Readable stream; stream modes; message.commit() | Rewrite loops, start positions, manual commits, and shutdown. |
| Data & serialization | String offsets/timestamps; object headers | bigint, Map; optional serializers; raw Buffer by default | Update types and JSON handling; preserve the existing wire format. |
| Transactions | producer.transaction() | producer.beginTransaction() | Set idempotent: true and transactionalId. |
| Operational APIs | KafkaJS events, errors, and Admin methods | node:diagnostics_channel; different error and Admin APIs | Migrate monitoring, error handling, and Admin calls. |
The consumer rewrite is the main migration risk. Test partition ordering, commit timing, rebalances, and graceful shutdown with in-flight records.
Producer migration also needs wire-level verification. A serialization change can alter message keys, JSON encoding, headers, or Schema Registry framing even when the TypeScript values look equivalent.
Migrating from KafkaJS to confluent-kafka-javascript
Confluent provides an official KafkaJS migration guide for its compatibility layer. The main processing APIs remain familiar, but configuration placement and some runtime behavior differ.
| Area | KafkaJS | confluent-kafka-javascript | Migration impact |
|---|---|---|---|
| Imports & config | KafkaJS configuration shapes | KafkaJS namespace; nested kafkaJS blocks | Move compatible options; map TLS and librdkafka settings separately. |
| Producer options | Per-send acks, compression, and timeout | Set during producer creation | Move all three options; review batching and flush(). |
| Consumer options | fromBeginning on subscribe(); auto-commit on run() | Set during consumer creation; 5-second auto-commit interval by default | Move options; autoCommitThreshold is unsupported. |
| Consumer handlers | eachMessage / eachBatch; callable heartbeat | Same handler names; client-built batches; automatic heartbeats | Test batch resolution, concurrency, rebalances, and commits. |
| Unsupported APIs | Custom networking, partitioners, assigners, and consumer.stop() | Unsupported in the compatibility layer | Replace broker functions and socketFactory; use disconnect(). |
| Errors & Admin | KafkaJS errors, retries, and Admin methods | Prefer error.code; different retries; subset Admin API | Update error branches, retry assumptions, and Admin calls. |
| Native packaging | Pure JavaScript | librdkafka native addon | Verify binaries in CI, containers, and production. |
| Schema Registry | @kafkajs/confluent-schema-registry | Keep it or adopt Confluent's package | Treat a package change as a separate migration. |
Applications using transactions need an additional check: a transactional producer cannot send outside an active transaction, and sendOffsets() receives the consumer instead of a consumer group ID.
Code churn is lower than with Platformatic, but verify rebalance, commit, retry, and error semantics and native binaries on every target.
Repository signals
The tables below compare the four clients' GitHub activity, maintenance, and public usage using the same metrics and assessment rules. Snapshot: 28 Aug 2026.
Project overview
| Attribute | Platformatic Kafka | KafkaJS | confluent-kafka-javascript | node-rdkafka |
|---|---|---|---|---|
| Repository created | 28 Feb 2025 | 1 Aug 2017 | 7 Nov 2023 | 11 Aug 2016 |
| License | Apache-2.0 | MIT | MIT | MIT |
Activity
| Metric | Platformatic Kafka | KafkaJS | confluent-kafka-javascript | node-rdkafka |
|---|---|---|---|---|
| Latest default-branch commit | 26 Aug 2026 | 16 May 2024 | 27 Aug 2026 | 3 Dec 2025 |
| Latest GitHub Release | v2.11.0 (25 Aug 2026) | v2.2.4 (27 Feb 2023) | v1.10.1-alpha.0 (26 Aug 2026) | v3.6.1 (3 Dec 2025) |
| GitHub Releases (12 mo) | 54 | 0 | 21 | 2 |
| Commits | 69 (90 d) · 218 (12 mo) | 0 (90 d) · 0 (12 mo) | 12 (90 d) · 83 (12 mo) | 0 (90 d) · 2 (12 mo) |
| Issue flow (90 d) | 27 opened · 33 closed | 8 opened · 1 closed | 7 opened · 3 closed | 3 opened · 0 closed |
| PR flow (90 d) | 50 opened · 55 merged | 10 opened · 0 merged | 26 opened · 12 merged | 2 opened · 0 merged |
| Activity assessment | 🟢 69 commits and 55 merged PRs in the last 90 days. | 🔴 No commit on the default branch in 834 days. | 🟢 12 commits and 12 merged PRs in the last 90 days. | 🔴 No commits and no merged PRs in the last 90 days. |
Release figures cover GitHub Releases, not npm. Confluent's latest GitHub entry is a prerelease; the capability table uses the stable 1.10.0 release.
Maintenance
| Metric | Platformatic Kafka | KafkaJS | confluent-kafka-javascript | node-rdkafka |
|---|---|---|---|---|
| Active commit authors (12 mo) | 29 | 0 | 14 | 1 |
| PR merge distribution (12 mo) | 2 people · largest share: 76% | 0 people · no recorded non-bot merges | 13 people · largest share: 36% | 1 person · largest share: 100% |
| Issue backlog | 0 open issues | 355 open · median age 3.8 y | 76 open · median age 1.4 y | 107 open · median age 3.3 y |
| Issue closure rate | 21/22 closed within 30 d · 21/22 within 90 d | N/A — no issues in measurement window | 4/10 closed within 30 d · 5/10 within 90 d | N/A — no issues in measurement window |
| PR backlog | 2 open · median age 67 d | 62 open · median age 2.3 y | 34 open · median age 192 d | 22 open · median age 1.7 y |
| Median PR merge time (90 d) | 1.2 d (n=55) | N/A — no merged PRs in window | 23.3 h (n=12) | N/A — no merged PRs in window |
| Responsiveness assessment | 🟡 Median open PR age is 67 d. | 🔴 No PRs merged in 90 d, while 62 open PRs have a median age of 2.3 y. | 🟡 New PRs merge in a median of 23.3 h (n=12), but 34 open PRs have a median age of 192 d. | 🔴 No PRs merged in 90 d, while 22 open PRs have a median age of 1.7 y. |
| PR merge concentration assessment | 🟡 2 people merged PRs in 12 mo; the most active account handled 76% of merges. | N/A — no recorded non-bot PR mergers in 12 mo | 🟢 13 people merged PRs in 12 mo; the most active account handled 36% of merges. | 🔴 1 person merged PRs in 12 mo and handled 100% of merges. |
PR merge distribution counts non-bot mergedBy accounts, so automated merges may undercount human reviewers. Issue closure rates use issues opened 90–180 days before the snapshot, giving each issue a full 90-day window.
Public usage and interest
| Metric | Platformatic Kafka | KafkaJS | confluent-kafka-javascript | node-rdkafka |
|---|---|---|---|---|
| Stars | 410 | 4,004 | 303 | 2,211 |
| Forks | 49 | 600 | 43 | 403 |
| GitHub dependents (Used by) | 40 | 32,281 | 11 | 2,561 |
| Public usage assessment | 🔴 Limited visible usage | 🟢 Broadest visible usage | 🔴 Limited visible usage | 🟡 Established visible usage |
GitHub dependents are approximate public-repository counts.
Overall repository signals
- Platformatic Kafka has the strongest recent activity, but it is the youngest project, has limited visible adoption, and recorded PR merging is concentrated among two people.
- KafkaJS has by far the broadest visible adoption, but its default branch and releases are inactive and its issue and PR backlogs are old.
- confluent-kafka-javascript is active and PR merging is distributed across more contributors, but visible adoption remains limited and its PR backlog is aging.
- node-rdkafka has established visible adoption, but it has no recent commits or merged PRs and recorded PR merging is concentrated in one person.
These are maintenance and adoption signals, not evidence of runtime quality or performance.
Test JavaScript Kafka clients with Kafma
A resolved send() does not prove that the stored bytes, headers, or schema framing match downstream expectations.
Kafma lets you inspect Kafka records and send controlled test traffic from one desktop workspace, without writing temporary debugging scripts.
Inspect records and test consumers in Console
Run your application producer against a test topic, then inspect the record in Kafma:
- Check encoding: With Schema Registry configured, Kafma automatically decodes Avro, Protobuf, and JSON Schema records. Switch between Decoded and Raw to verify the decoded value, schema ID, and original bytes.
- Check metadata: Verify the stored key, headers, partition, offset, and timestamp, especially after changing serializers or header mappings.

Keep the application consumer running, then use Kafma's built-in producer to send controlled test records:
- Manual: Send edge-case payloads, tombstones, custom headers, or fixed-partition records.
- File: Load CSV, JSON, or JSONL data for repeatable batch tests. Available with Kafma Pro.
- Loop: Generate continuous test traffic while observing batching, backpressure, and shutdown with in-flight records.

Clone production-shaped data for migration tests
Simple test data rarely reflects everything in a production topic. Older schema versions, tombstone records with null values, unusual keys, and missing headers can expose migration problems.
Kafma Data Clone copies a bounded time or offset range into a local or staging cluster. With Structure + Data, it can create a missing target topic, register the required schemas, and copy keys, values, timestamps, headers, and tombstones. Optional masking can redact selected sensitive fields.

Frequently asked questions
Should an existing KafkaJS application migrate?
Keep KafkaJS if the application is stable and its feature set and maintenance path remain acceptable. Choose confluent-kafka-javascript when you need KIP-848, GSSAPI/Kerberos, first-party Schema Registry support, or commercial support with fewer API changes. Choose Platformatic Kafka when staying pure JavaScript matters and the application can adopt its Node.js requirements and stream-based consumer.
Is a pure JavaScript client always easier to deploy?
It usually simplifies packaging by avoiding platform-specific native binaries. Runtime compatibility still matters: Platformatic Kafka requires Node.js 22.22+ or 24.6+, while KafkaJS supports older Node.js versions.
Which clients support the KIP-848 consumer group protocol?
Platformatic Kafka, confluent-kafka-javascript, and node-rdkafka support KIP-848; KafkaJS does not. KIP-848 requires Kafka 4.0+ brokers. For the two librdkafka clients, set group.protocol=consumer; the classic protocol remains the default. Treat adoption as a consumer migration and test configuration, assignments, rebalances, and commits.
Does librdkafka automatically make a client faster?
No. Throughput depends on message size, batching, compression, acknowledgements, network latency, consumer concurrency, and application overhead. Benchmark the complete workload with comparable settings.
Can services using different JavaScript clients share a topic or consumer group?
They can share a topic when they agree on key and value serialization, headers, Schema Registry framing, and partitioning assumptions. Consumers sharing a group must also use the same group protocol and compatible assignment behavior; test rebalances and offset commits before mixing clients in production.
Conclusion
For a new pure-JavaScript service, start with Platformatic Kafka when its Node.js requirements and stream-based consumer fit. Choose confluent-kafka-javascript when you need a KafkaJS-like API, GSSAPI/Kerberos, first-party Schema Registry support, or commercial support. Keep KafkaJS or node-rdkafka in a stable existing service unless a missing capability justifies migration.
This guide is maintained by the team behind Kafma.