BullMQ provides several methods for removing jobs from queues, from removing individual jobs to bulk cleanup operations.
Remove Individual Job
Remove a specific job by its ID, along with all its dependencies:
Method Signature
async remove(
jobId: string,
opts?: { removeChildren?: boolean }
): Promise<number>
The ID of the job to remove
If true, also removes child jobs in flows. Set to false to keep child jobs.
Returns: 1 if the job was removed successfully, 0 if the job or any of its dependencies were locked.
Example
import { Queue } from 'bullmq';
const queue = new Queue('tasks');
// Remove a job
const removed = await queue.remove('job-id-123');
if (removed === 1) {
console.log('Job removed successfully');
} else {
console.log('Job could not be removed (may be locked)');
}
// Remove without removing children
await queue.remove('parent-job-id', { removeChildren: false });
When a job is removed, a removed event is emitted by the queue.
Drain
Removes all jobs that are waiting or delayed, but not active, waiting-children, completed, or failed jobs.
Method Signature
async drain(delayed?: boolean): Promise<void>
If true, also removes delayed jobs
Examples
import { Queue } from 'bullmq';
const queue = new Queue('tasks');
// Drain waiting jobs only
await queue.drain();
// Drain both waiting and delayed jobs
await queue.drain(true);
Parent Job Behavior
- Parent jobs in the queue being drained will be kept in waiting-children status if they have pending children. If they have no pending children, they will be removed.
- Parent jobs in other queues will stay in waiting-children if they have pending children elsewhere, or be moved to wait if all their children are gone.
Clean
Removes jobs in a specific state, keeping only jobs within a grace period. Similar to drain but more targeted.
Method Signature
async clean(
grace: number,
limit: number,
type?: 'completed' | 'wait' | 'waiting' | 'active' | 'paused' | 'prioritized' | 'delayed' | 'failed'
): Promise<string[]>
Grace period in milliseconds. Jobs older than this will be removed.
Maximum number of jobs to clean
type
string
default:"completed"
The type of jobs to clean. Can be: completed, wait, waiting, active, paused, prioritized, delayed, or failed.
Returns: Array of deleted job IDs
Examples
import { Queue } from 'bullmq';
const queue = new Queue('tasks');
// Clean completed jobs older than 1 minute
const deletedIds = await queue.clean(
60000, // 1 minute grace period
1000, // max 1000 jobs to clean
'completed'
);
console.log(`Cleaned ${deletedIds.length} completed jobs`);
// Clean failed jobs older than 1 hour
await queue.clean(
3600000, // 1 hour
5000, // max 5000 jobs
'failed'
);
// Clean paused jobs older than 5 minutes
await queue.clean(
300000, // 5 minutes
100,
'paused'
);
The clean method triggers a cleaned event with the deleted job IDs and the job type.
Obliterate
Completely destroys a queue and all of its contents irreversibly. Use with extreme caution.
Method Signature
async obliterate(opts?: ObliterateOpts): Promise<void>
Use force: true to obliterate even with active jobs in the queue
Maximum number of keys to delete per iteration
Examples
import { Queue } from 'bullmq';
const queue = new Queue('old-queue');
// Normal obliterate (pauses queue first, requires no active jobs)
await queue.obliterate();
// Force obliterate even with active jobs
await queue.obliterate({ force: true });
// Obliterate with custom batch size
await queue.obliterate({ count: 500 });
This operation is irreversible and will delete all queue data. The queue will be paused first. Parent jobs in other queues will either stay in waiting-children if they have pending children elsewhere, or be moved to wait.
This operation may be slow for very large queues as it must iterate over all jobs.
Specialized Removal Methods
Remove Deduplication Key
Removes a deduplication key, allowing duplicate jobs to be added again:
await queue.removeDeduplicationKey('unique-key-123');
Remove Rate Limit Key
Removes the rate limit key, clearing any active rate limiting:
await queue.removeRateLimitKey();
Remove Job Scheduler
Removes a job scheduler (repeatable job):
const removed = await queue.removeJobScheduler('scheduler-id');
Practical Examples
Example 1: Periodic Cleanup
import { Queue } from 'bullmq';
const queue = new Queue('tasks');
// Run cleanup every hour
setInterval(async () => {
// Clean completed jobs older than 1 day
const completed = await queue.clean(
86400000, // 24 hours
10000,
'completed'
);
// Clean failed jobs older than 7 days
const failed = await queue.clean(
604800000, // 7 days
10000,
'failed'
);
console.log(`Cleaned ${completed.length} completed, ${failed.length} failed jobs`);
}, 3600000); // Every hour
Example 2: Queue Reset
import { Queue } from 'bullmq';
const queue = new Queue('tasks');
async function resetQueue() {
// Drain all waiting jobs
await queue.drain(true);
// Clean all completed jobs
await queue.clean(0, Infinity, 'completed');
// Clean all failed jobs
await queue.clean(0, Infinity, 'failed');
console.log('Queue reset complete');
}
await resetQueue();
Example 3: Graceful Queue Deletion
import { Queue, Worker } from 'bullmq';
const queue = new Queue('deprecated-queue');
const worker = new Worker('deprecated-queue', async job => {
// Process job
});
async function deleteQueue() {
// 1. Stop accepting new jobs (pause queue)
await queue.pause();
// 2. Wait for worker to finish active jobs
await worker.close();
// 3. Obliterate the queue
await queue.obliterate();
// 4. Close queue connection
await queue.close();
console.log('Queue deleted successfully');
}
await deleteQueue();