npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

bun-threads

v1.1.1

Published

Abstractions around Bun workers to enable working with them as promises.

Readme

bun-threads

Multithreading for the Bun Runtime Made Simple 🧵

bun-threads is a lightweight, developer-friendly TypeScript library for Bun that makes it effortless to offload tasks into separate worker threads. It wraps worker threads and messaging with a clean, promise-based interface and type support, enabling easy parallel processing without any boilerplate or separate worker files. bun-threads makes writing multithreaded JavaScript and TypeScript feel more like writing the asynchronous single threaded code that you are used to.

🔧 Features

  • Simple API: Create and run worker threads easily using the Thread and ThreadPool classes.

  • Type-Safe: Written in pure Typescript. Arguments and return values are automatically typed.

  • Automatic Scaling: Manage thread lifecycle and scaling without verbose setup code.

  • Low Config: Works out of the box. No setup files or separate worker files required.

  • Tested: Uses native bun:test library to ensure proper coverage and code quality. File | % Funcs | % Lines | Uncovered Line #s ---------------|---------|---------|------------------- All files | 93.83 | 99.02 | thread.ts | 92.00 | 99.06 | threadpool.ts | 95.65 | 98.99 | ---------------|---------|---------|-------------------

    51 pass

    0 fail

    100 expect() calls

    Ran 51 tests across 1 file. [1233.00ms]

Installation

bun add bun-threads

❓ FAQ

Why not just use one of the existing libraries that does this like workerpool, multithreading.io, tinypool, poolifier, threads.js, etc?

  • They're great projects, but they either don't work properly in Bun (workerpool is almost there), or they require that you to create a separate worker file, which is something that this library aims to avoid.

What makes this library Bun specific?

  • Currently this library is using one small Bun specific API and Bun's implementation of Node's Worker API. Using Bun's actual native Worker API is planned for the future, but as it's still experimental, it has a few bugs in it that make it unfeasible to use at the moment. Once the native Bun Worker API stabilizes, a full switchover to the native API will be made to take advantage of the performance gains.

My program is hanging and not exiting after introducing multithreading. Why?

  • Make sure that you are calling the Thread.close() or ThreadPool.close() method when you are done with the instance. Instances of Thread close themselves by default after completing all of their queued run() calls if no idleTimeout was specified or if idleTimeout is set to 0. Instances of ThreadPool keep at least minThreads number of Threads open by default for faster startup times on subsequent run() calls. Setting an instance of ThreadPool's minThreads to 0 will also cause all of it's underlying Thread instances to close themselves after completing each run() call, similar to how an instance of a single Thread behaves.

I keep getting ReferenceError: x is not defined. How do I fix this?

  • Check your imports. Worker threads don't have access to your top level imports at the top of your file. Instead, use dynamic imports inside of your thread's callback function.
    // incorrect example:
    import { availableParallelism } from "os";
    const badThread = new Thread(() => {
        console.log(availableParallelism())
    })
    badThread.run() // throws ReferenceError: availableParallelism is not defined
      
    // correct example:
    const goodThread = new Thread(async () => {
        const os = await import("os")
        console.log(os.availableParallelism())
    })
    goodThread.run() // works correctly

Examples

Quick Multithreading Proof:

import { Thread } from "bun-threads";

const proof = new Thread(() => Bun.isMainThread)

console.log('Thread isMainThread:', await proof.run())
console.log('Main process isMainThread:', Bun.isMainThread)

Simple Demo Function:

import { Thread } from "bun-threads";

const addThread = new Thread((a: number, b: number) => {
    return a + b
})

addThread.run(21, 21).then((result) => console.log(result))

Thread vs ThreadPool:

import { Thread, ThreadPool } from "bun-threads";

const thread = new Thread((wait: number) => Bun.sleepSync(wait)) // simulate some synchronous work
const threadPool = new ThreadPool((wait: number) => Bun.sleepSync(wait)) // simulate some synchronous work

let start = performance.now()
await Promise.all([,
    thread.run(1_000),
    thread.run(1_000),
    thread.run(1_000)
])
// a single Thread can only execute synchronous tasks one at a time
console.log('Thread completed in:', performance.now() - start, 'ms') // ~ 3000 ms

start = performance.now()
await Promise.all([,
    threadPool.run(1_000),
    threadPool.run(1_000),
    threadPool.run(1_000)
])
// ThreadPool runs each task in a separate Thread in parallel
console.log('ThreadPool completed in:', performance.now() - start, 'ms') // ~ 1000 ms

thread.close()
threadPool.close()

Changelog

1.1.1

  • Fixed nested promises in Thread.run() and ThreadPool.run() return types. Example: Both methods will now return Promise<string> instead of Promise<Promise<string>>.

1.1.0

  • You no longer have to pass arguments to Thread.run() or ThreadPool.run() as arrays. Intellisense should now pick up on argument types and amounts automatically.