Skip to content

Concurrency runtime for JavaScript

Move JavaScript
off the main thread.

pool.ts
import { createPool, isMain } from "knitting";

export const hello = (name: string) => "hello " + name;

if (isMain) {
  using pool = createPool({
    threads: 1,
  })({ hello });

  console.log(await pool.call.hello("world"));
}
❯ bun run pool.ts
hello world
host bun · main thread
await pool.call.hello("world")

same process, shared memory

One call site, whether work runs in a thread or an isolated process.
npm install knittingnpm + JSR
0runtime dependencies
1typed API
2worker boundaries
3JavaScript runtimes

A simpler worker API

From an exported function to a worker call.

No worker entry point, message router, or response plumbing. Define tasks at the module level, pass them to a pool, and keep the call site typed.

main.tsTypeScript
import { createPool, isMain } from "knitting";
export const square = (value: number) => value * value;
export const greet = (name: string) => `hello ${name}`;
if (isMain) {
using pool = createPool({ threads: 2 })({ square, greet });
const [four, message] = await Promise.all([
pool.call.square(2),
pool.call.greet("knitting"),
]);
console.log({ four, message });
}
  1. 01
    Export the task

    Plain functions are tasks. Add task() only when you need options.

  2. 02
    Create the pool

    Choose threads for speed or processes for stronger isolation.

  3. 03
    Call it like any function

    The result is a promise. Errors come back as standard Error objects.

InstallReady in one dependency.
npm install knitting
deno add --npm knitting
Installation details

The effect at the server edge

Keep fast routes fast.

On the Hono example’s mixed workload, React SSR and JWT leave the request thread. /ping never enters the pool, yet handles 201% more requests under saturation because it no longer waits behind expensive routes.

Hono + SSR + JWT + Zod benchmark

Throughput (requests/sec, higher is better)

  • /ping +201%
    before 2,815 after 8,486
  • /ssr +71%
    before 2,815 after 4,816
  • /jwt +83%
    before 2,578 after 4,712
/ping p99 latency 86% lower

The mechanics around the call

The boundary is part of the API.

Knitting handles the mechanics that make workers useful in production: moving data, isolating code, scheduling work, and preserving stack traces and error causes.

Fast by construction

Move the work, not all the bytes.

Pass typed payloads and promises. Move large buffers through zero-copy handles. Set timeouts, cancel with abort signals, and keep stack traces and error causes intact. Knitting’s native work stealing lets compatible multi-worker pools claim tasks from a shared submit region instead of waiting in private request lanes.

  • Promise inputs
  • SharedArrayBuffer
  • ProcessSharedBuffer
  • BufferReference
  • Task timeouts
  • Abort signals
  • Typed arrays
  • Error cause chains
  • Native work stealing
Explore payloads

Choose your boundary

Use threads for trusted work. Use processes for isolation.

The same task API works with runtime threads or isolated processes. Combine importTask with permissions, bubblewrap, or a container.

threadprocesssandbox
Choose a boundary

Failure is part of the API

Deadlines, cancellation, and clear errors.

Limit cooperative work with timeouts and abort signals, or hard-kill runaway CPU work after a deadline. Stack traces and error causes come back intact.

Define resilient tasks

Observable on demand

Quiet by default. Detailed when debugging.

Enable only the diagnostics you need: host setup, imports, lifecycle, signals, or global state. When disabled, the logger is not imported.

Configure a pool

Adaptive scheduling

Keep every worker moving.

Compatible multi-worker pools share one submit region, so workers can claim tasks as they become free. On Node.js and Bun thread pools, the host doorbell can wait for completions instead of repeatedly polling. The task API stays the same.

  • Work stealing
  • Shared submit region
  • Private return lanes
  • Host doorbell

Explore scheduling details

Measured in practice

Low-latency IPC.

These measurements come from the public benchmark suite. Review the methodology, hardware, and raw results before comparing workloads.

Scheduling roundtrip538ns

Node · 53.8 μs per batch of 100

Zero-copy roundtrip816ns

Node · 81.6 μs per batch of 100

1 MiB copied round-trip313μs

Bun · 31.3 ms per batch of 100

Keep the function. Move the heavy work.

Keep CPU-heavy work off the event loop.

Knitting is the middle ground between running CPU-heavy work on the request thread and moving it to a separate service. Keep the work in your application without blocking the event loop.

Tested on every push

The hard parts are the tested parts.

Tests cover what is easy to get wrong: shared-memory transport, work stealing, deadlines, payload limits, permissions, and the published package itself. All of it runs on Node.js, Deno, and Bun, on Linux, macOS, and Windows.

400+tests in the suite
90%line coverage floor on Node
3operating systems in CI

Your hot path can stay a function.

Give it a better place to run.

Start with one exported task. Add stronger isolation only when you need it.