Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

770 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bunqueue

npm version npm downloads CI GitHub Stars License

High-performance job queue for Bun. Built for AI agents and automation.
Zero external infrastructure. MCP-native. TypeScript-first.

Documentation · Quick Start · Benchmarks · npm


Quickstart

bun add bunqueue
import { Bunqueue } from 'bunqueue/client';

const app = new Bunqueue('emails', {
  embedded: true,
  dataPath: './data/emails.db', // omit to run in-memory (lost on restart)
  processor: async (job) => {
    console.log(`Sending to ${job.data.to}`);
    return { sent: true };
  },
});

await app.add('send', { to: 'alice@example.com' });

That's it. Queue + Worker in one object, persisted to a single SQLite file. No Redis, no config, no setup. The install is 5.5 MB, 7 packages, 2 runtime dependencies (croner + msgpackr) — SQLite, S3, HTTP and WebSocket are Bun built-ins.

Not on Bun? Run the server, connect from anywhere

The queue also runs as a standalone server — one command, nothing else to operate:

# in-memory without --data-path; pass it to persist jobs to SQLite
bunx bunqueue start --data-path ./data/bunq.db   # TCP :6789, HTTP :6790

# or, with no runtime at all (the volume persists /app/data):
docker run -d -p 6789:6789 -p 6790:6790 \
  -v bunqueue-data:/app/data \
  ghcr.io/egeominotti/bunqueue:latest

Then produce and process from the language you already use:

npm install bunqueue-client    # Node.js ≥ 20, Deno ≥ 2, Bun, Cloudflare Workers
import { Queue, Worker } from 'bunqueue-client';

const queue = new Queue('emails');                       // localhost:6789 by default
await queue.add('welcome', { to: 'user@example.com' });

new Worker('emails', async (job) => ({ sent: true }), { concurrency: 10 });

Python, PHP, Go, Rust and Elixir clients speak the same protocol — see One Queue, Any Language.

Only the server and embedded mode are Bun-only (bun >= 1.3.9, bun.sh); producers and workers can run anywhere.

Quick Start guide →

Why bunqueue?

Library Requires AI-native
BullMQ Redis No
Agenda MongoDB No
pg-boss PostgreSQL No
bunqueue Nothing Yes
  • Zero external infrastructure — one process, one SQLite file. cp to back up
  • BullMQ-compatible API — same Queue, Worker, QueueEvents; migrating takes minutes
  • MCP server included — 73 tools; AI agents get full queue control out of the box
  • Everything server-side — retries with backoff, priorities, cron, rate limits, dead letter queue
  • Up to 630K ops/secverified benchmarks with methodology

Great for: single-server deployments, AI agents that need a scheduler, prototypes and MVPs, embedded use cases (CLI tools, edge, serverless), teams that don't want to operate Redis.

Not ideal for: multi-region distributed systems requiring HA or automatic failover today. If you already run Redis and BullMQ works for you, keep it.

When to choose bunqueue →

Two Modes

Embedded Server (TCP)
How it works Queue runs inside your process Standalone server, clients connect via TCP
Setup bun add bunqueue docker run or bunqueue start
Performance 630K ops/sec (bulk push) 90K ops/sec (push)
Best for Single-process apps, CLIs, serverless Multiple workers, separate producer/consumer
Scaling Same process only Multiple clients across machines

Embedded

Everything in your process. Without a data path the queue is in-memory: pass dataPath (or set BUNQUEUE_DATA_PATH) to persist jobs.

import { Queue, Worker } from 'bunqueue/client';

const queue = new Queue('emails', { embedded: true, dataPath: './data/app.db' });

const worker = new Worker(
  'emails',
  async (job) => {
    return { sent: true };
  },
  { embedded: true }
);

await queue.add('welcome', { to: 'user@example.com' });

Server (TCP)

docker run -d -p 6789:6789 -p 6790:6790 \
  -v bunqueue-data:/app/data \
  ghcr.io/egeominotti/bunqueue:latest
import { Queue, Worker } from 'bunqueue/client';

const queue = new Queue('tasks', { connection: { host: 'localhost', port: 6789 } });

const worker = new Worker(
  'tasks',
  async (job) => {
    return { done: true };
  },
  { connection: { host: 'localhost', port: 6789 } }
);

await queue.add('process', { data: 'hello' });

Running the server → · Deployment guide →

One Queue, Any Language (SDKs)

The server does all the heavy lifting. Official client SDKs speak the native TCP protocol with full feature parity, so producers and workers can live anywhere in your stack — add a job from TypeScript, process it from Python:

Where your code runs Install
Node.js ≥ 20, Deno ≥ 2, Bun, Cloudflare Workers npm install bunqueue-client
Python ≥ 3.9 pip install bunqueue-client
PHP ≥ 8.1 composer require bunqueue/client
Go ≥ 1.26.5 go get github.com/egeominotti/bunqueue/sdk/go
Rust ≥ 1.85 cargo add bunqueue-client
Elixir ≥ 1.15 Hex coming soon — today: use sdk/elixir as a path dependency
// Node.js / Deno / Cloudflare Workers
import { Queue, Worker } from 'bunqueue-client';

const queue = new Queue('emails', { host: 'localhost', port: 6789 });
await queue.add('welcome', { to: 'user@example.com' });

new Worker('emails', async (job) => ({ sent: true }), { concurrency: 10 });
# Python
from bunqueue import Queue, Worker

queue = Queue("emails", host="localhost", port=6789)
queue.add("welcome", {"to": "user@example.com"})

Worker("emails", lambda job: {"sent": True}, concurrency=10).run()

Every SDK is certified against the same public wire protocol and conformance suite.

SDK guide (all six languages) →

Simple Mode

Bunqueue bundles Queue + Worker + routes + middleware + cron in one object:

import { Bunqueue } from 'bunqueue/client';

const app = new Bunqueue('notifications', {
  embedded: true,
  routes: {
    'send-email': async (job) => ({ sent: true }),
    'send-sms': async (job) => ({ sent: true }),
  },
  concurrency: 10,
  retry: { maxAttempts: 5, strategy: 'jitter' },
  circuitBreaker: { threshold: 5, resetTimeout: 30000 },
});

// Onion middleware around every job
app.use(async (job, next) => {
  const start = Date.now();
  const result = await next();
  console.log(`${job.name}: ${Date.now() - start}ms`);
  return result;
});

await app.cron('daily-report', '0 9 * * *', { type: 'summary' });
await app.add('send-email', { to: 'alice@example.com' });

app.on('completed', (job, result) => console.log(result));
await app.close();

Also included: batch processing, event triggers (job A completes → create job B), job TTL, priority aging, deduplication, per-group rate limiting, DLQ with auto-retry, graceful cancellation via AbortController.

Simple Mode reference →

Workflow Engine

Multi-step orchestration with saga compensation, branching, parallel steps and human-in-the-loop signals — built on bunqueue, no new infrastructure:

import { Workflow, Engine } from 'bunqueue/workflow';

const orderFlow = new Workflow('order-pipeline')
  .step('reserve-stock', async () => {
    await inventory.reserve();
    return { reserved: true };
  }, {
    compensate: async () => await inventory.release(), // auto-rollback on failure
  })
  .step('charge', async () => {
    return { txId: await payments.charge() };
  }, {
    compensate: async () => await payments.refund(),
  })
  .waitFor('manager-approval', { timeout: 86_400_000 }) // human-in-the-loop
  .step('confirm', async (ctx) => {
    return { txId: (ctx.steps['charge'] as { txId: string }).txId };
  });

const engine = new Engine({ embedded: true });
engine.register(orderFlow);
const run = await engine.start('order-pipeline', { orderId: 'ORD-1' });
await engine.signal(run.id, 'manager-approval', { approved: true });
bunqueue Temporal Inngest Trigger.dev
Infrastructure None (embedded) PostgreSQL + 7 services Cloud-only Redis + PostgreSQL
Saga compensation Built-in Manual Manual Manual
Human-in-the-loop .waitFor() Signals API step.waitForEvent() Waitpoint tokens
Self-hosted Zero-config Complex No Complex
Pricing Free (MIT) Free / Cloud $$ Per-execution Free tier, then $50/mo+

Also included: nested workflows, doUntil/doWhile loops, forEach over dynamic lists, schema validation (Zod, ArkType, Valibot or any .parse()), step timeouts, typed events, SQLite-persisted execution state.

Workflow Engine guide →

Built for AI Agents (MCP Server)

bunqueue ships a native MCP server: 73 tools, 5 resources, 3 prompts. Agents schedule cron jobs, push and process jobs, retry failures, set rate limits, and read stats — no glue code. HTTP handlers let an agent register a URL and have an embedded worker call it for every job.

bun add bunqueue @modelcontextprotocol/sdk   # the MCP SDK is an optional peer
claude mcp add bunqueue -- bunx bunqueue-mcp
// Claude Desktop / Cursor / Windsurf
{
  "mcpServers": {
    "bunqueue": {
      "command": "bunx",
      "args": ["--package=bunqueue", "bunqueue-mcp"]
    }
  }
}

Then just ask: "Schedule a cleanup job every day at 3 AM" · "Show me all failed jobs and retry them" · "Set rate limit to 50/sec on api-calls".

MCP guide →

Dashboard

A web dashboard that fully drives your server — queues, jobs, DLQ, cron, webhooks, workers, live activity, SQLite inspector and an AI copilot. Open source, currently in beta:

bunx bunqueue-dashboard
bunqueue-demo.mp4

Live demo · User guide · GitHub

Performance

Mode Peak Throughput Use Case
Embedded 630K ops/sec (bulk push) Same process
TCP 90K ops/sec (push) Distributed workers

Run bun run bench to verify on your hardware. Benchmark methodology →

Documentation

bunqueue.dev →

License

MIT

Releases

Packages

Used by

Contributors

Languages