Queues
⚡ Feature powered by BullMQ
Make your API breathe. Offload slow or bursty work (emails, webhooks, reports, 3rd-party calls) to background jobs—without ceremony.
What this plugin gives you
- BullMQ power, CrumbJS DX: queues & workers wired in minutes.
- Jobs as classes: extend
Queueable<T>
and decorate with@IsQueueable()
. - Auto-discovery: handlers are registered on startup—no manual wiring.
- Retries, backoff & delays: resilient by default.
- Concurrency control: tune throughput per worker.
- Type-safe payloads: generics keep your job data honest.
Great for
- Transactional emails, webhook fan-out, data exports, cache warming, long-running tasks, and cron-like scheduling.
Heads-up: you’ll need a reachable Redis server (host/port or auth).
Install
Let's install the plugin, on your api directory run:
bun install @crumbjs/bullmq
Mount
Options
type PluginOptions = {
/** Redis HOST @default '127.0.0.1' */
host: string;
/** Redis PORT @default 6379 */
port: number;
/** Redis USERNAME @default undefined */
user?: string;
/** Redis PASSWORD @default undefined */
pass?: string;
/**
* Amount of jobs that a single worker is allowed to work on in parallel.
* @default 10
*/
concurrency: number;
};
import { App } from "@crumbjs/core";
import { bullmqPlugin } from "@crumbjs/bullmq";
/* options are optional */
const app = new App();
app.use(bullmqPlugin(options));
app.serve();
Define a queueable
Create a class that extends Queueable
and decorate it with @IsQueueable()
and define how to handle it
@IsQueueable()
decorator register the event type and event handler at api startup.
import { IsQueueable, Queueable } from "@crumbjs/bullmq";
@IsQueueable()
class WelcomeEvent extends Queueable<{ clientId: string }> {
// default options
// void
async handle() {
await EmailService.sendWelcome(this.payload.clientId);
}
}
@IsQueueable()
class SendEmail extends Queueable<{ to: string }> {
/**
* How many times the job will be retried on failure.
* @optional @default 5
*/
public override retries: number = 5;
/**
* Delay in milliseconds before retrying a failed job.
* @optional @default 15000
*/
public override delayOnFailure: number = 15000;
/**
* If true, removes the job when it successfully completes When given a number,
* it specifies the maximum amount of jobs to keep, or you can provide an object specifying max age and/or count to keep.
* @optional @default true (delete job after complete)
*/
public override removeOnComplete: boolean | number = true;
/**
* If true, removes the job when it fails after all attempts. When given a number,
* it specifies the maximum amount of jobs to keep, or you can provide an object specifying max age and/or count to keep.
* @optional @default 100 (keep 100 failed attempts in redis)
*/
public override removeOnFail: boolean | number = 100;
async handle() {
console.log(`Email to ${this.getPayload().to}`);
}
}
Queueing an event anywhere in your Crumbjs Api
import { dispatch } from "@crumbjs/bullmq";
dispatch(new SendEmail({ to: "alice@example.com" }));
Easy? right?