← Back to archive

Repo of the Day

piscinajs/piscina

Published: Jul 7, 2023

Open repository ↗

A fast, efficient Node.js Worker Thread Pool implementation

Summary

Piscina is a Node.js worker thread pool library written in TypeScript that distributes JavaScript tasks across a configurable pool of node:worker_threads. It targets Node.js 24.x and higher and supports CommonJS, ESM, and TypeScript code in both the main thread and worker files.

What it is useful for

Piscina is useful when you need to run CPU-bound JavaScript work in parallel without blocking the main event loop. Typical use cases include image transformation, cryptographic hashing, parsing large JSON or CSV files, compression, and any computation that benefits from spreading across CPU cores. It bundles features you would otherwise build yourself around node:worker_threads: a task queue with maxQueue-based backpressure, run-time and wait-time histograms, cancellation through AbortSignal (or any EventEmitter or EventTarget that emits 'abort'), and per-worker memory limits through resourceLimits. On Linux, you can also lower worker scheduling priority through niceIncrement so the pool does not starve other processes, and the library tracks file descriptors opened with fs.open() and closes them on worker exit when trackUnmanagedFds is enabled.

How engineers can use it

Create a worker module that exports a function or async function, then point Piscina at it. The README's main example exports ({ a, b }) => a + b from worker.js, while the main file creates new Piscina({ filename: path.resolve(__dirname, "worker.js") }) and awaits piscina.run({ a: 4, b: 6 }). A single worker file can expose multiple named handlers, dispatched with piscina.run(task, { name: "multiply" }). To cancel an in-flight task, pass an AbortSignal as the signal option to run(). For streaming producers, set maxQueue: "auto" and listen for the 'drain' and 'needsDrain' events to pause and resume the source. Read-only properties such as queueSize, idleThreads, utilization, runTime (a histogram with p50 and p99 percentiles), and waitTime make it straightforward to expose metrics. Shut down with await piscina.close() to drain in-flight tasks or await piscina.destroy() to abort them. A documented gotcha: any async work scheduled inside a worker but not awaited before the handler returns will resume on the next task, so await all promises before returning. The README does not include a dedicated install section, so check the project website and the repo's examples/ directory for additional usage patterns.