Skip to content
Get started
Get started
Introduction: SQLite Job Queue for Bun
guide · introduction

The queue that is a file.

bunqueue is a job queue for the Bun runtime. It stores jobs in SQLite, so there is no Redis and no extra server to run. Add a job now, a worker processes it in the background, and nothing is lost on restart.

A job queue lets your app hand off slow work (sending emails, processing images, calling APIs) to run in the background instead of blocking a request. bunqueue gives you that with one bun add, no external infrastructure.

import { Queue, Worker } from 'bunqueue/client';
const queue = new Queue('emails', { embedded: true });
const worker = new Worker('emails', async (job) => {
console.log('Sending to', job.data.to);
return { sent: true };
}, { embedded: true });
await queue.add('welcome', { to: 'user@example.com' });

Run it with bun run app.ts. No server: the queue runs embedded in your process.

That is a complete, working queue. The Quick Start walks through it step by step.

  • Zero infrastructure. Jobs persist in SQLite, a single file on disk. No Redis, no broker. Only 2 runtime dependencies, a 5.5 MB install.
  • Native Bun. Built on bun:sqlite for performance, around 100k jobs/sec in the default mode.
  • Familiar API. If you know BullMQ, you already know most of bunqueue.
  • Production features. Retries with backoff (automatic waiting between retry attempts), a dead letter queue (a holding area for jobs that keep failing), cron scheduling, rate limiting, stall detection, and S3 backups.
  • AI-agent ready. A built-in MCP server with 73 tools lets agents like Claude add jobs, manage crons, and monitor queues via natural language.
EmbeddedServer
What it isA library inside your processA standalone bunqueue process
Best forSingle-process apps, scripts, serverlessMultiple services sharing one queue
SetupPass embedded: trueRun bunqueue start, then connect
PersistencedataPath option--data-path flag

Embedded mode means the queue lives inside your app, like using SQLite instead of Postgres:

import { Queue, Worker } from 'bunqueue/client';
// Both must have embedded: true
const queue = new Queue('tasks', { embedded: true });
const worker = new Worker('tasks', async (job) => { /* ... */ }, { embedded: true });

Server mode runs bunqueue as its own process, and any number of apps connect to it over TCP:

Terminal window
bunqueue start --data-path ./data/queue.db
// No embedded option = connects to localhost:6789
const queue = new Queue('tasks');
const worker = new Worker('tasks', async (job) => { /* ... */ });

Server mode also unlocks clients in other runtimes: Node.js, Deno, Python, PHP, Go, Rust, Elixir, and Cloudflare Workers via the client SDKs.

FeaturebunqueueBullMQ
RuntimeBunNode.js
StorageSQLiteRedis
External depsNoneRedis server
Priorities, delays, retries, cronYesYes
Rate limiting, stall detection, flowsYesYes
Advanced DLQ (auto-retry, filters)YesBasic
S3 backupsYesNo
MCP server for AI agentsYes (73 tools)No
Built-in workflow engineYesNo

Migrating? The API is intentionally close to BullMQ, see the migration guide.

For multi-step processes (validate an order, charge, notify, ship) bunqueue ships a workflow engine with retries, parallel steps, branching, rollback on failure, and human-in-the-loop signals:

import { Workflow, Engine } from 'bunqueue/workflow';
const flow = new Workflow('order')
.step('validate', async (ctx) => ({ ok: true }))
.step('charge', async (ctx) => ({ txId: 'tx_123' }), { retry: 3 })
.waitFor('approval')
.step('ship', async (ctx) => ({ shipped: true }));

No Temporal, no extra service. See the Workflow Engine guide.