Bun
Every package in this workspace (@cookiemonsterdev/kafka-core, -config, -cli, and -studio)
runs on Node.js and on Bun. This page covers what differs on Bun.
Supported versions
| Runtime | Supported | Tested on |
|---|---|---|
| Node.js | >=24 |
24 and 26 |
| Bun | >=1.4 |
1.4 |
Both ranges are declared in each package’s engines field. The CLI and studio check the runtime
when they start and exit with a clear message on an older Bun or Node.js. Under Bun,
process.versions.node reports a Node.js compatibility version, so the check reads
process.versions.bun instead. Do the same if your own code needs to detect Bun.
Install the packages with bun add as usual. The monorepo itself is developed with pnpm.
Running the CLI and studio
The kafka and kafka-studio binaries start with a #!/usr/bin/env node shebang, so bunx and
bun run start them on Node.js unless you pass --bun before the package name:
bunx --bun @cookiemonsterdev/kafka-cli ping --brokers localhost:9092
bunx --bun @cookiemonsterdev/kafka-studio
The CLI and studio installation pages have the full details: CLI on Bun and studio on Bun.
Config loading
Config file loading works the same way on both runtimes, with these differences on Bun:
- Bun transpiles TypeScript natively, so a
kafka.config.tswith a TypeScriptenumor an extensionless relative import loads without the Node.js transform fallback, and without its warning. On Node.js, write erasable TypeScript instead. - The synchronous loader used by
new Kafka()canrequire()a config file that uses top-levelawait, so it does not throwKafkaConfigRequiresAsyncError. - The deprecated
installConfigTransformHooks()does nothing, because Bun’snode:modulehas noregisterHooks.
Synchronous TS/JS config loading in new Kafka() is deprecated on both runtimes, and the
config.sync-load-deprecated warning still appears on Bun. Prefer await Kafka.fromConfig(), or
use kafka.config.json.
TLS
Bun’s TLS and node:crypto are built on BoringSSL rather than OpenSSL, so some
ssl options that work on Node.js are unavailable:
- DSA and RSA-PSS keys and certificates
- CCM and OCB cipher modes, and chacha20-poly1305 through
node:crypto - OCSP stapling
- TLS-PSK (
pskCallback)
TLS session resumption also doesn’t carry over from one process to another. Brokers with standard RSA or ECDSA certificates and default cipher suites work on both runtimes.
Native optional packages
The optional native packages (kerberos for SASL/GSSAPI, and snappy and lz4 for faster
compression) load on Bun through N-API, with two caveats:
-
bun installdoesn’t run dependency install scripts by default, so the addon is never built. List each package you use in your app’strustedDependencies:{ "trustedDependencies": ["kerberos", "snappy", "lz4"] } -
An addon built for Node.js 24 doesn’t load on Bun 1.4, which reports
NODE_MODULE_VERSION147. If you switch runtimes on an existing install, reinstall or rebuild the addon under Bun.
Without the native snappy and lz4 packages, the client uses its built-in pure-JS codecs. Those
need no setup on either runtime.
Performance and workers
- CRC32C. On Node.js, record batch checksums use
crypto.hash('crc32c')when OpenSSL provides it. BoringSSL doesn’t, so on Bun every checksum uses the built-in JavaScript implementation. The result is identical; only large batches see a small CPU cost. - GZIP and ZSTD use
node:zlibon both runtimes. - Snappy and LZ4 run on a
worker_threadspool on both runtimes. Bun ignores workerresourceLimits. The client’s pool doesn’t set any, but if you run your own codecs in workers, memory caps you set there aren’t enforced on Bun.
How we test
CI runs every package’s unit test suite on Node.js 24 and 26, and again on Bun 1.4. On each of
those runtimes, a smoke test then loads the built packages the way an application would: it
imports each one, runs the kafka and kafka-studio executables, round-trips Snappy and LZ4
through the compression workers (and checks that the process still exits on its own), and loads a
TypeScript config file. Integration tests against real brokers run on Node.js only.
See also: Compatibility for broker versions and the implemented API surface.