About bullmq
bullmq is a skill for working with BullMQ queues, workers, scheduling, retries, and related integrations. It helps developers inspect the project's versions and backend, choose appropriate APIs, and verify queue behavior.
Key features
- 01Inspect BullMQ versions and datastore setup
- 02Guide queue and worker configuration
- 03Handle job flows, retries, and scheduling
- 04Cover Redis and PostgreSQL backend choices
- 05Verify processing and operational behavior
Use cases
- 01Changing queue or worker code in a BullMQ project
- 02Configuring retries, delayed jobs, or recurring tasks
- 03Evaluating Redis or PostgreSQL queue backends
- 04Testing queue integrations and graceful shutdown
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ dobroslavradosavljevic/ skills --skill bullmqAfter installing, type/bullmqin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
agents/openai.yamlreferences/flows.mdjobs-options.mdproduction-ops-integrations.mdretries-scheduling-limits.mdsetup-connections.mdsource-map.mdDetails
From the project READMEBullMQ
Use this skill when work touches BullMQ queues, workers, flows, retries/scheduling, NestJS BullMQ, PostgreSQL vs Redis backends, or Pro-vs-OSS decisions.
Snapshot: [email protected] (2026-10-01). Refresh from source-map.md if the installed major/minor differs.
Workflow
- Inspect the local BullMQ surface before changing code:
- Package versions for
bullmq, optional peers (ioredis,redis,pg,bullmq-otel),@nestjs/bullmqif present, Node/Bun, and TypeScript. - Backend: default Redis (
connectionoptions or a client) vscreatePostgresBackend/setDefaultBackendFactory. - Connection shape: options object vs shared client vs adapters (
createNodeRedisClient,createBunRedisClient,createValkeyGlideClient); Redisprefixvs Postgresschema. - Producers (
Queue,FlowProducer) vs consumers (Worker); process isolation (inline vs sandboxed file / worker threads). - Default job options, schedulers, rate limits, dedupe usage, Nest module registration if present.
- Package versions for
- Refresh current official docs when the task depends on latest APIs, version drift, Pro features, adapters, Postgres, or Nest wrappers. Start from source-map.md.
- Route the work to the focused references:
- Setup, Redis/Postgres backends, Queue, Worker, QueueEvents: setup-connections.md.
- Job lifecycle and JobsOptions: jobs-options.md.
- Parent-child flows / FlowProducer: flows.md.
- Retries, delays, job schedulers, rate limits, dedupe: retries-scheduling-limits.md.
- Ops, v5→v6 upgrade, testing, NestJS, Pro vs OSS, polyglot: production-ops-integrations.md.
- Preserve the repository's existing connection factories, Nest modules, and deployment topology unless the user explicitly asks for a migration.
- Verify behavior at the narrowest useful boundary (processor unit), then queue/worker integration.
Core Judgment
- Treat the datastore as shared infrastructure. Reuse connection options or factories deliberately. Workers and QueueEvents still duplicate connections for blocking wait; Redis clients/adapters must support
duplicate(). - Default Redis path requires the optional
ioredispeer. Do not assumebullmqstill bundles ioredis. ioredis 6.0 (RESP3 by default, Node 20+) satisfies the>=5.0.0peer range, but BullMQ still tests against ioredis 5.11 and an open issue reports ioredis 6RedisOptionsnot assignable toConnectionOptions. Preferbun add bullmq ioredis@5unless the project already runs ioredis 6 and its typecheck + integration tests pass. - Non-Redis backends (Postgres or custom): pass the factory last and let TypeScript infer backend + connection types, or bind once with
withBackend(createPostgresBackend)(6.3.9+) when you also need job type arguments. Never write partial generics likeQueue<Data, Result, string, PostgresQueueBackend>— the 4thQueueslot is not the backend. - High-level classes are datastore-agnostic. Do not use removed
Queue#client,Queue#redisVersion,Queue#databaseType,Worker#blockingClient, orFlowProducer#client. Reach Redis viaqueue.getBackend().client(typed asRedisQueueBackend) only as an escape hatch. waitUntilReady()resolves tovoid. Do not treat its return as a Redis client.await worker.resume().- Attach
errorlisteners onQueue,Worker,QueueEvents, andFlowProducer. Unhandled connection errors crash Node. - Design processors as idempotent. Jobs can retry, stall after lock loss, or run more than once.
- Set
attemptsandbackoffintentionally. ThrowUnrecoverableErrorfor poison/permanent failures (Job#discard()is removed). ThrowErrorobjects, not strings. - Prefer
FlowProducerfor parent-child graphs. Flow parents must not setdeduplication. Flow job opts omitrepeat. Nodes withoutopts.jobIdget UUIDs. Pick child failure opts deliberately (failParentOnFailure,ignoreDependencyOnFailure,removeDependencyOnFailure,continueParentOnFailure). - Recurring work is Job Schedulers only:
upsertJobScheduler/getJobSchedulers/removeJobScheduler. Do not resurrectQueue.add(..., { repeat }),Repeat,getRepeatableJobs,removeRepeatable,removeRepeatableByKey,debounce,Job#debounceId, thedebouncedevent,QueueScheduler, or pre-v3groupKeyrate limits on BullMQ 6.x. Group rate limits are Pro-only. - Deduplication needs a stable
deduplication.id. Choose simple vs throttle (ttl) vs debounce (extend/replace+delay) vskeepLastIfActive. - Rate limiting is global per queue across workers. Prefer
queue.rateLimit(Worker#rateLimitis deprecated). Optional queue-levelsetGlobalConcurrency/setGlobalRateLimitcap all workers; per-workerconcurrency/limitercannot exceed them. - Priority: lower number wins among prioritized jobs (
1..2097151); unset/0is unprioritized and is processed before any prioritized job. Paused queues still hold jobs as waiting —pausedis not a job state ingetJobCounts()/JobType. - Tune
removeOnComplete/removeOnFail(age or count keep policies). Unbounded completed/failed sets grow without bound. Never use iorediskeyPrefix; use BullMQprefix(brace hash tags on Cluster). Postgres usesschema, not Redis prefix. - Close workers gracefully on shutdown (
await worker.close()). Killing processes mid-lock causes stalls and duplicate work unless ops expect that window. - Prefer
@nestjs/bullmqover legacy@nestjs/bull. Do not recommend BullMQ Pro-only APIs (groups, group rate limits, workerjob.getBatch(), observables) unless the project already uses Pro. - Keep processors thin and non-blocking on the event loop. Use sandboxed processors /
useWorkerThreadswhen CPU-heavy or crash-isolating work is required. Jobdatais plaintext — avoid secrets or encrypt fields. - Redis remains the default, battle-tested backend. Use PostgreSQL (
createPostgresBackend, explicitrunMigrations) only when the project chooses a single-database model. Do not mix Redis and Postgres for the same queue.
Verification
Prefer repository-owned commands. For meaningful BullMQ changes, cover the relevant subset:
- Typecheck Queue/Worker/FlowProducer options (including backend generic), job
data/returnvalue/ProgressTypetypes, and Nest injection tokens if used. - Unit-test processor success, retryable failure,
UnrecoverableError, progress, and AbortSignal cancellation in isolation. - Integration test against Redis or Postgres: add → process → complete/fail; assert job state transitions.
await worker.waitUntilReady()before adding jobs (returns void). - Delayed/scheduler tests with short intervals; assert no duplicate schedules after redeploy (
upsertJobScheduler). Confirm no leftoverrepeat/getRepeatableJobsusage. - Rate-limit / dedupe tests: assert ignored/replaced/deferred behavior and
deduplicatedevents (notdebounced). - Flow tests: children complete before parent; parent reads
getChildrenValues; child failure policy matches product intent; parent nodes rejectdeduplication. - Stall/lock smoke when changing
lockDuration,stalledInterval,maxStalledCount, or long-running processors. - Graceful-shutdown smoke: SIGTERM/
closepath finishes in-flight work without unexpected orphaned locks beyond the stall window. - NestJS module smoke: queue registration,
WorkerHostprocessors, and FlowProducer injection when Nest is in play. - Postgres:
runMigrationsapplied;SchemaVersionMismatchError/SchemaMigrationRequiredErrornot hit at boot. - Redis growth check when changing retention (
removeOnComplete/removeOnFail) or adding high-throughput queues.
Report which checks ran, which did not, and any Pro/OSS, Redis-vs-Postgres, or package-version assumptions that remain.