Skip to content
GuidesDocs 1.3.x

Runtime Compatibility ​

Published @connectum/* packages declare Node.js >=22.13.0 in their package manifests. The framework repository itself requires Node.js >=26.0.0 for development. CI runs the framework test matrix on Node.js 24 and 26, and tests the HTTP/2 client boundary on Bun 1.2.6 and the current Bun release. Those are separate contracts: the framework's development floor does not raise the published packages' engine requirement.

Runtime switcher

Pages that show runtime-specific commands have a Node.js | Bun switch in the navigation bar (and next to each affected block). This page deliberately shows both runtimes side by side.

Scaffolding emits runtime-appropriate defaults

connectum init --runtime bun (see Scaffolding a Service) emits Bun-appropriate defaults — the bun test runner and the in-process createLocalClient test transport, which opens no socket and behaves identically on both runtimes. The CLI itself is exercised on Node.js, so run it with npx even inside a Bun project.

Runtime requirements and CI coverage ​

UseVersion requirement or tested boundaryEvidence
Run published framework packages on Node.js>=22.13.0Each published package manifest declares this engines.node floor.
Develop in the framework repository>=26.0.0The workspace manifest declares this floor.
Run package tests in framework CI on Node.js24 and 26CI's Node.js test matrix; the workspace development engine remains >=26.0.0.
Run generated TypeScript directly with Node.js>=25.2.0 with --node-exec rawThe CLI's generated engine range and runtime option.
Run generated TypeScript with Node.js and tsx>=22.13.0 with --node-exec tsxThe CLI's generated engine range and runtime option.
Use the HTTP/2 client on Bun>=1.2.6CI checks the floor version and a latest Bun channel; the full suite runs on the latest channel.

For observed client behavior, see HTTP/2 Client Transport. Each example may set a higher runtime floor for its own source, so check its package.json before choosing a runtime. The CLI itself is exercised on Node.js only; run it with npx even when the generated project targets Bun.

HTTP/2 Client Transport ​

Node.js ​

On Node.js, HTTP/2 gRPC clients work out of the box with createGrpcTransport():

typescript
import { createClient } from '@connectrpc/connect';
import { createGrpcTransport } from '@connectrpc/connect-node';
import { GreeterService } from '#gen/greeter/v1/greeter_pb.js';

const transport = createGrpcTransport({
  baseUrl: 'http://localhost:5000',
  httpVersion: '2',
});

const client = createClient(GreeterService, transport);
const res = await client.sayHello({ name: 'Alice' });

This uses Node.js native node:http2 module for full HTTP/2 multiplexing.

Bun ​

Bun >= 1.2.6 needs no special client code -- the snippet above works unchanged. Unary, server-streaming and bidi-streaming calls over createGrpcTransport() and createConnectTransport({ httpVersion: '2' }) all complete, and status codes carried in HTTP/2 trailers arrive intact.

Bun's node:http2 client was incomplete before 1.2.6: on those versions the transport is constructed without error and the first RPC hangs -- the call never completes and no error is thrown. Bun 1.2.6 rewrote the node:http2 client and closed this.

Bun <= 1.2.5

Upgrade Bun. If you cannot, the only working option is createConnectTransport() over HTTP/1.1 (the default httpVersion):

typescript
import { createClient } from '@connectrpc/connect';
import { createConnectTransport } from '@connectrpc/connect-node';
import { GreeterService } from '#gen/greeter/v1/greeter_pb.js';

const transport = createConnectTransport({
  baseUrl: 'http://localhost:5000',
  // httpVersion defaults to '1.1' -- omit or set explicitly
});

const client = createClient(GreeterService, transport);
const res = await client.sayHello({ name: 'Alice' });

That path carries unary and server-streaming calls but not bidi streaming, gives up HTTP/2 multiplexing, and requires the server to accept HTTP/1.1 (allowHTTP1: true, the default). Connectum servers speak the Connect protocol alongside gRPC, so no server change is needed.

The recorded tests cover the server on Bun 1.1.38 and later tested versions, including plaintext h2c (allowHTTP1: false). The historical limitation above concerns the client; it is not evidence for untested Bun server versions.

Streaming RPC ​

Node.js ​

On Node.js, both unary and streaming RPCs work with createGrpcTransport() or createConnectTransport():

typescript
import { createClient } from '@connectrpc/connect';
import { createGrpcTransport } from '@connectrpc/connect-node';
import { MonitorService } from '#gen/monitor/v1/monitor_pb.js';

const transport = createGrpcTransport({
  baseUrl: 'http://localhost:5000',
  httpVersion: '2',
});

const client = createClient(MonitorService, transport);

// Server streaming -- works with any transport
for await (const event of client.watchEvents({ filter: 'error' })) {
  console.log(`Event: ${event.type} -- ${event.message}`);
}

Bun ​

The same code runs on Bun -- no runtime branching is needed, and Connectum itself contains none.

  • Server streaming works on every Bun version tested, over both HTTP/2 and HTTP/1.1 transports.
  • Bidi streaming requires HTTP/2, and therefore Bun >= 1.2.6 for the client. This is a protocol constraint, not a Bun one: bidi streaming is impossible over HTTP/1.1 on any runtime, and Connectum refuses to start a server that hosts bidi methods on plaintext HTTP/1.1 (CONNECTUM_UNSUPPORTED_STREAMING_TRANSPORT).

Do not hand-build a fetch transport

Earlier revisions of this page suggested createTransport() from @connectrpc/connect/protocol-connect together with createFetchClient(globalThis.fetch). Do not use that pattern: createTransport is marked internal by ConnectRPC and is not covered by semantic versioning, and on Bun 1.1.x it silently drops the request body.

Testing Utilities ​

@connectum/testing provides mock helpers including createMockNext(), createMockNextError(), createMockNextSlow(), and createMockFn(). Their implementation does not import node:test; this alone does not establish support for every test runner or runtime.

typescript
import { describe, it } from 'node:test'; // or 'bun:test'
import { createMockNext, createMockRequest } from '@connectum/testing';

describe('my interceptor', () => {
  it('calls next', async () => {
    const next = createMockNext();
    await myInterceptor(next)(createMockRequest());
    // next.mock.callCount() === 1
  });
});

createMockFn() is API-compatible with the subset of node:test's mock.fn() that the testing helpers rely on (.mock.calls, .mock.callCount()), so assertions written against one runtime work on the other. Full API: @connectum/testing.

The @connectum/testing/parity subpath registers a node:test test (transportParityTest) and therefore runs on Node.js only. The mock helpers shown above are separate from that subpath.

OpenTelemetry ​

@connectum/otel uses the OpenTelemetry SDK packages declared by the module. Node.js is covered by the package test suite. The framework's Bun CI matrix skips @connectum/otel, so this project does not publish a Bun compatibility claim for its tracing, metrics, or logging behavior. The package does not include @opentelemetry/auto-instrumentations-node; validate any separately installed auto-instrumentation against your runtime.

WARNING

If you use @connectum/otel on Bun, test the specific exporter and instrumentation packages in your application. This repository does not validate that combination.

Known Issues ​

IssueRuntimeStatusWorkaround
HTTP/2 client transports (createGrpcTransport(), createConnectTransport({ httpVersion: '2' })) hang on the first RPCBun <= 1.2.5Fixed in Bun 1.2.6Upgrade Bun; on older Bun use createConnectTransport() over HTTP/1.1 (no bidi)
node:test mock API unavailableBunBy designUse bun:test mock directly
@connectum/testing/parity requires node:testBunNode.js test registrationUse the main entry point in Bun tests; run parity tests on Node.js
@connectum/cli is exercised on Node.js onlyBunOpenRun the CLI with npx; generated code is unaffected
@connectum/otel runtime behaviorBunNot covered by this project's Bun test suiteValidate the selected exporters and instrumentation in your application