Make failed work retryable.
Retries with backoff, stall recovery and a dead letter queue you can inspect and replay.
Retries & recoveryBackground jobs for Node.js, Deno, Python, PHP, Go, Rust, Elixir and Bun. Free, open source, hosted by you.
TCP :6789TCP :6789Free, including the server.Every queue feature ships under MIT.
Your infrastructure.Run locally, on a VPS, or in Docker.
Bun app? Embed it.Queue and worker in one process.
Choose how to run the queue. Both options are free, with the same core queue features.
With Docker running, choose a base and copy the command. No Bun installation needed.
The default: a compact musl base with a shell and apk. Same bunqueue features on AMD64 and ARM64.
docker run -d --name bunqueue \ --restart unless-stopped \ -p 127.0.0.1:6789:6789 \ -p 127.0.0.1:6790:6790 \ -v bunqueue-data:/app/data \ egeominotti/bunqueue:alpineA full Debian base with glibc, a shell and apt. Same bunqueue features on AMD64 and ARM64.
docker run -d --name bunqueue \ --restart unless-stopped \ -p 127.0.0.1:6789:6789 \ -p 127.0.0.1:6790:6790 \ -v bunqueue-data:/app/data \ egeominotti/bunqueue:debianDebian with glibc, a shell and apt, with fewer bundled utilities. Same bunqueue features on AMD64 and ARM64.
docker run -d --name bunqueue \ --restart unless-stopped \ -p 127.0.0.1:6789:6789 \ -p 127.0.0.1:6790:6790 \ -v bunqueue-data:/app/data \ egeominotti/bunqueue:slimRequired runtime libraries only. No shell or package manager. Same bunqueue features on AMD64 and ARM64.
docker run -d --name bunqueue \ --restart unless-stopped \ -p 127.0.0.1:6789:6789 \ -p 127.0.0.1:6790:6790 \ -v bunqueue-data:/app/data \ egeominotti/bunqueue:distrolessCheck that the server is ready:
curl --fail http://127.0.0.1:6790/healthPorts stay local to your machine. SQLite data persists in the volume when you replace the container. Run one variant at a time.
These tags follow new releases. Pin a version or digest for deployment.
In a terminal with Bun installed, start the included server. Keep it running.
bunx bunqueue start --host 127.0.0.1 --data-path ./bunqueue.dbThis is a local process on your machine. The server is included in the MIT-licensed package.
Open another terminal. Install a client, save the example, then run it.
npm install bunqueue-clientimport { Queue, Worker } from 'bunqueue-client';
const options = { embedded: false, connection: { host: '127.0.0.1', port: 6789 },};const queue = new Queue('emails', options);
const worker = new Worker( 'emails', async (job) => { console.log('Processing:', job.data.to); return { sent: true }; }, options);
worker.on('error', (error) => console.error(error));await queue.add('welcome', { to: 'hello@example.com' });node jobs.mjsdeno add npm:bunqueue-clientimport { Queue, Worker } from 'bunqueue-client';
const options = { embedded: false, connection: { host: '127.0.0.1', port: 6789 },};const queue = new Queue<{ to: string }>('emails', options);
const worker = new Worker<{ to: string }>( 'emails', async (job) => { console.log('Processing:', job.data.to); return { sent: true }; }, options);
worker.on('error', (error) => console.error(error));await queue.add('welcome', { to: 'hello@example.com' });deno run --allow-net --allow-env --allow-sys=hostname jobs.tspip install bunqueue-clientfrom bunqueue import Queue, Worker
connection = {"host": "127.0.0.1", "port": 6789}queue = Queue("emails", **connection)queue.add("welcome", {"to": "hello@example.com"})queue.close()
def process(job): print("Processing:", job.data["to"]) return {"sent": True}
Worker("emails", process, **connection).run()python jobs.pyYou should see Processing: hello@example.com. Your application and worker use the same queue name and TCP address.
Use embedded mode when your app and worker run together on Bun. The queue engine lives inside your application.
bun add bunqueueSet embedded: true on both the queue and worker. The example keeps jobs in memory; configure SQLite persistence to recover work after a restart.
import { Queue, Worker } from 'bunqueue/client';
const queue = new Queue<{ to: string }>('emails', { embedded: true });
const worker = new Worker<{ to: string }>( 'emails', async (job) => { console.log('Processing:', job.data.to); return { sent: true }; }, { embedded: true });
worker.on('error', (error) => console.error(error));await queue.add('welcome', { to: 'hello@example.com' });bun jobs.tsStart with a queue and a worker. Add the controls your workload needs.
Retries with backoff, stall recovery and a dead letter queue you can inspect and replay.
Retries & recoveryPriorities, delayed jobs, rate limits, concurrency controls and FIFO groups.
Queue controlsCron schedules and parent-child job flows. A separate workflow engine adds in-process orchestration on Bun.
Flows & dependenciesJob queries, Prometheus metrics, health probes and events. Connect AI tools through the native MCP server.
Monitoring & operationsOfficial clients share the Queue/Worker/Flow core. Check the SDK capability matrix for language-specific APIs.
Choose storage when you need it. Your application keeps the same queue API.
Keep the Queue and Worker mental model. bunqueue uses its own engine and protocol, with SQLite or PostgreSQL for persistence.
Read the migration guideMoving a Node.js app?Use bunqueue-client and connect to a bunqueue server. Your application stays on Node.js.
Check the differences first.Review compatibility and scheduling behavior in the full comparison. Explore the benchmark methodology for performance evidence.
The cost, the name, and the connection.
bunqueue is completely free and open source under the MIT license. The server, clients and queue features are included. There is no paid plan or feature paywall. If you rent a server or database, you pay your infrastructure provider.
The core engine uses Bun and its native APIs. The standalone server and embedded runtime require Bun. Network clients use their own runtime, including Node.js, Deno, Python, PHP, Go, Rust and Elixir.
No. Start the included server on your machine or your own infrastructure, then point your client at its host and TCP port. A Bun application can also use embedded mode without a separate server.
For server mode, start the server first and use a reachable hostname with TCP port 6789. Port 6790 is the HTTP API. Inside Docker, localhost refers to that container. For embedded mode, run on Bun and set embedded: true on both Queue and Worker.
Free and open source, from the first local job to production.
Explore the documentation