Skip to content
Get started
Get started

bunqueue Quick Start: Build a Bun Job Queue in 5 Minutes

blog · quick start

Background jobs in five minutes.

From zero to processing jobs before your coffee cools. This guide covers embedded mode, the simplest setup, and TCP server mode for distributed systems.

Embedded mode runs the queue engine inside your application process. No server needed.

  1. Install bunqueue

    Terminal window
    bun add bunqueue
  2. Create a queue and add jobs

    import { Queue } from 'bunqueue/client';
    interface EmailJob {
    to: string;
    subject: string;
    body: string;
    }
    const queue = new Queue<EmailJob>('emails', { embedded: true });
    await queue.add('welcome', {
    to: 'user@example.com',
    subject: 'Welcome!',
    body: 'Thanks for signing up.',
    });
  3. Create a worker to process jobs

    import { Worker } from 'bunqueue/client';
    const worker = new Worker<EmailJob>(
    'emails',
    async (job) => {
    console.log(`Sending email to ${job.data.to}`);
    // Your email sending logic here
    await job.updateProgress(100);
    return { sent: true };
    },
    { embedded: true, concurrency: 3 }
    );
    worker.on('completed', (job, result) => {
    console.log(`Job ${job.id} completed:`, result);
    });
    worker.on('failed', (job, err) => {
    console.error(`Job ${job.id} failed:`, err.message);
    });
  4. Run your application

    Terminal window
    bun run app.ts

That’s it. Jobs are persisted to SQLite automatically. If your app crashes and restarts, pending jobs are recovered.

Jobs support priorities, delays, retries, and timeouts:

// High priority job - processed before lower priority jobs
await queue.add('urgent-alert', data, { priority: 10 });
// Delayed job - processed after 30 seconds
await queue.add('reminder', data, { delay: 30_000 });
// Custom retry configuration
await queue.add('payment', data, {
attempts: 5,
backoff: { type: 'exponential', delay: 1000 },
timeout: 60_000,
});
// Idempotent job - same jobId won't be added twice
await queue.add('daily-report', data, { jobId: 'report-2024-01-15' });

For multi-process architectures, run bunqueue as a standalone server:

Terminal window
# Start the server
bunqueue start --tcp-port 6789 --data-path ./data/queue.db

Then connect from your application:

import { Queue, Worker } from 'bunqueue/client';
// Producer - connects via TCP
const queue = new Queue<EmailJob>('emails', {
connection: { host: 'localhost', port: 6789 },
});
await queue.add('send', { to: 'user@example.com', subject: 'Hello' });
// Worker - also connects via TCP
const worker = new Worker<EmailJob>(
'emails',
async (job) => {
// process job
return { sent: true };
},
{ connection: { host: 'localhost', port: 6789 }, concurrency: 5 }
);

Check job status and queue health:

// Get job counts by state
const counts = await queue.getJobCountsAsync();
console.log(counts);
// { waiting: 10, active: 3, completed: 150, failed: 2, delayed: 5 }
// Get a specific job
const job = await queue.getJob('job-id-here');
console.log(job?.data, job?.progress);
// Queue control
await queue.pause(); // Stop processing
await queue.resume(); // Resume processing

Now that you have the basics running, check out: