Migration from BullMQ
This guide helps you migrate from BullMQ to bunqueue with minimal code changes.
Overview
bunqueue provides a BullMQ-compatible API, making migration straightforward for most use cases.
| BullMQ | bunqueue | Notes |
|---|---|---|
new Queue() | new Queue() | ✅ Same API |
new Worker() | new Worker() | ✅ Same API |
QueueEvents | QueueEvents | ✅ Same API |
FlowProducer | FlowProducer | ✅ Same API |
jobId deduplication | jobId deduplication | ✅ Same behavior (idempotent) |
| Redis connection | Not needed | ✅ Simpler |
Step 1: Install bunqueue
# Remove BullMQ and Redisbun remove bullmq ioredis
# Install bunqueuebun add bunqueueStep 2: Update Imports
// Before (BullMQ)import { Queue, Worker, QueueEvents } from 'bullmq';import Redis from 'ioredis';
const connection = new Redis();const queue = new Queue('my-queue', { connection });
// After (bunqueue)import { Queue, Worker, QueueEvents } from 'bunqueue/client';
const queue = new Queue('my-queue', { embedded: true });// No connection needed - uses in-process SQLite!Step 3: Remove Redis Configuration
// Before (BullMQ)const queue = new Queue('emails', { connection: { host: 'localhost', port: 6379, password: 'secret', }, defaultJobOptions: { attempts: 3, backoff: { type: 'exponential', delay: 1000 }, },});
// After (bunqueue)const queue = new Queue('emails', { embedded: true, defaultJobOptions: { attempts: 3, backoff: 1000, // Base delay for exponential backoff },});Step 4: Update Worker
// Before (BullMQ)const worker = new Worker('emails', async (job) => { await sendEmail(job.data); return { sent: true };}, { connection, concurrency: 5, limiter: { max: 100, duration: 1000 },});
// After (bunqueue)const worker = new Worker('emails', async (job) => { await sendEmail(job.data); return { sent: true };}, { embedded: true, concurrency: 5, // Rate limiting is set on queue via server mode, not worker});
// Rate limiting is configured via CLI or TCP server// bunqueue rate-limit set emails 100Step 5: Update Events
Events work the same way:
// Same in both BullMQ and bunqueueworker.on('completed', (job, result) => { console.log(`Job ${job.id} completed`);});
worker.on('failed', (job, err) => { console.error(`Job ${job.id} failed:`, err.message);});
worker.on('progress', (job, progress) => { console.log(`Job ${job.id}: ${progress}%`);});Step 6: Update Job Options
// Before (BullMQ)await queue.add('task', data, { priority: 1, delay: 5000, attempts: 3, backoff: { type: 'exponential', delay: 1000 }, removeOnComplete: true, removeOnFail: false, jobId: 'custom-id',});
// After (bunqueue) - Almost identical// Queue created with: new Queue('tasks', { embedded: true })await queue.add('task', data, { priority: 1, delay: 5000, attempts: 3, backoff: 1000, // Base delay (exponential: 1s, 2s, 4s, 8s...) removeOnComplete: true, removeOnFail: false, jobId: 'custom-id',});API Differences
Backoff Configuration
// BullMQ supports both typesbackoff: { type: 'exponential', delay: 1000 }backoff: { type: 'fixed', delay: 5000 }
// bunqueue only supports exponential backoffbackoff: 1000 // Base delay in msRate Limiting
// BullMQ (on worker)new Worker('queue', processor, { limiter: { max: 100, duration: 1000 }});
// bunqueue (server mode only - via CLI or TCP)// Rate limiting is not available in embedded modebunqueue rate-limit set my-queue 100Sandboxed Processors
// BullMQ sandboxed processorsnew Worker('queue', './processor.js', { connection });
// bunqueue SandboxedWorker (isolated Bun Worker processes)import { SandboxedWorker } from 'bunqueue/client';
const worker = new SandboxedWorker('queue', { processor: './processor.ts', concurrency: 4, timeout: 30000,});worker.start();Repeatable Jobs
// BullMQawait queue.add('task', data, { repeat: { cron: '0 * * * *' }});
// bunqueue (queue created with embedded: true)await queue.add('task', data, { repeat: { pattern: '0 * * * *' }});// Or use intervalawait queue.add('task', data, { repeat: { every: 3600000 }});Features Comparison
| Feature | BullMQ | bunqueue | Notes |
|---|---|---|---|
| Sandboxed processors | ✅ | ✅ | Use SandboxedWorker |
| Redis Cluster | ✅ | ❌ | Single instance |
| Redis Streams | ✅ | ❌ | SQLite storage |
| Rate limit per worker | ✅ | ❌ | Queue-level rate limit |
Migration Checklist
- Remove
bullmqandioredispackages - Install
bunqueue - Update imports to
bunqueue/client - Remove all Redis connection configuration
- Update backoff configuration (simplified)
- Move rate limiting from worker to queue
- Update sandboxed processors to use
SandboxedWorker - Update repeat config (
cron→pattern) - Test all job processing
- Remove Redis server from infrastructure
Getting Help
If you encounter issues during migration: