- Docs
- Reference
- TCP Protocol
- Control & Limits
Steer jobs, queues and limits.
Change individual jobs, pause, drain, clean and obliterate whole queues, and set rate limits, concurrency caps, job group controls and per-queue stall and DLQ configuration.
Part of the TCP protocol reference, which describes the framing, authentication, pipelining and response format that every command on this page uses.
Control Commands
Section titled “Control Commands”Cancel
Section titled “Cancel”Cancel a waiting or delayed job.
Request:
{ cmd: 'Cancel', id: string }Response:
{ ok: true;}Progress
Section titled “Progress”Update the progress of an active job.
Request:
{ cmd: 'Progress', id: string, progress: number, // 0-100 message?: string // Optional progress message}progress is stored as in 2.9.10 and never refused: a number is clamped to 0-100 (NaN
is 0); a numeric string, a boolean or null is its Number(...) ("50" is 50, true is
1); other text is 0 with the text as the message when none is given. Clients send
object progress as 0 with its JSON as the message.
Response:
{ ok: true;}Update
Section titled “Update”Update the data payload of an existing job.
Request:
{ cmd: 'Update', id: string, data: any // New job data}data must be JSON serializable (Job data must be JSON serializable). Unlike PUSH,
an update has no size limit, as in 2.9.10.
Response:
{ ok: true;}ChangePriority
Section titled “ChangePriority”Change the priority of a queued job.
Request:
{ cmd: 'ChangePriority', id: string, priority: number, lifo?: boolean // Tie-break ordering among same-priority jobs}priority can be any finite number, for grouped jobs too (as in 2.9.10; a numeric
string counts as its number); a missing priority is 0 (BullMQ’s
changePriority({ lifo: true })). lifo, when given, is made a boolean exactly as on
PUSH (1 is true, 0 is false). NaN, an infinity or a non-number fails
(priority must be a finite number, priority must be a number) and leaves the job
unchanged; a job that is not queued fails with Job not found or not in queue,
which the client SDKs treat as “not changed”, like embedded mode.
Response:
{ ok: true;}Promote
Section titled “Promote”Move a delayed job to the waiting state immediately.
Request:
{ cmd: 'Promote', id: string }Response:
{ ok: true;}MoveToDelayed
Section titled “MoveToDelayed”Move an active job back to the delayed state.
Request:
{ cmd: 'MoveToDelayed', id: string, delay: number, // Delay in ms from now (required, finite; negative = past run time) token?: string // Required when the active job has a lock}A missing or non-finite delay fails the command (delay is required,
delay must be a finite number, …) and leaves the job unchanged. As in 2.9.10, a
negative delay makes the job ready at once with a past run time (ahead of later ready
jobs; a PostgreSQL broker uses “now”, as on 2.9.10) and a very large one is applied (clamped at
about 136,900 years).
Response:
{ ok: true;}Discard
Section titled “Discard”Discard a job by moving it to the dead-letter queue.
Request:
{ cmd: 'Discard', id: string, token?: string }When the job has an active lease, token must match the current delivery
token. For waiting or otherwise unlocked jobs, the field may be omitted for an
administrative discard.
Response:
{ ok: true;}WaitJob
Section titled “WaitJob”Wait for a job to complete. This is event-driven (no polling). Returns immediately if the job is already completed.
Request:
{ cmd: 'WaitJob', id: string, timeout?: number // Max wait time in ms (default: 30000, max: 600000)}Response:
{ ok: true, completed: boolean, result?: any }Pause a queue. Workers will stop pulling new jobs.
Request:
{ cmd: 'Pause', queue: string }Response:
{ ok: true;}Resume
Section titled “Resume”Resume a paused queue.
Request:
{ cmd: 'Resume', queue: string }Response:
{ ok: true;}IsPaused
Section titled “IsPaused”Check whether a queue is currently paused.
Request:
{ cmd: 'IsPaused', queue: string }Response:
{ ok: true, paused: boolean }Remove all waiting and delayed jobs from a queue. Active jobs are not affected.
Request:
{ cmd: 'Drain', queue: string }Response:
{ ok: true, count: number } // Number of jobs removedObliterate
Section titled “Obliterate”Remove all data for a queue (all jobs in all states).
Request:
{ cmd: 'Obliterate', queue: string }Response:
{ ok: true;}Remove jobs older than a grace period, optionally filtered by state.
Request:
{ cmd: 'Clean', queue: string, grace: number, // Grace period in ms - jobs older than this are removed state?: string, // 'waiting'/'delayed'/'prioritized'/'paused' (queued jobs, the default), 'completed', or 'failed' limit?: number // Max jobs to remove (default: 1000)}Response:
{ ok: true, count: number, ids: string[] } // IDs of the removed jobsListQueues
Section titled “ListQueues”List the names of all known queues.
Request:
{ cmd: 'ListQueues';}Response:
{ ok: true, queues: string[] } // Queue namesFor per-queue counts use GetJobCounts per queue, or the HTTP GET /queues/summary endpoint.
Rate Limiting Commands
Section titled “Rate Limiting Commands”RateLimit
Section titled “RateLimit”Set a rate limit on a queue: limit jobs per duration ms (default 1000, so jobs per second).
Request:
{ cmd: 'RateLimit', queue: string, limit: number, // Max jobs per window duration?: number, // Window in ms (default 1000) ttl?: number // Auto-expiry in ms: the server clears the limit itself}Invalid duration or ttl values (non-finite or not positive) fall back to the defaults (1 second window, permanent limit) instead of failing. Servers older than 2.8.35 ignore both optional fields.
Response:
{ ok: true;}RateLimitClear
Section titled “RateLimitClear”Remove the rate limit from a queue.
Request:
{ cmd: 'RateLimitClear', queue: string }Response:
{ ok: true;}SetConcurrency
Section titled “SetConcurrency”Set a concurrency limit on a queue (max concurrent active jobs).
Request:
{ cmd: 'SetConcurrency', queue: string, limit: number}Response:
{ ok: true;}ClearConcurrency
Section titled “ClearConcurrency”Remove the concurrency limit from a queue.
Request:
{ cmd: 'ClearConcurrency', queue: string }Response:
{ ok: true;}GetQueueLimits
Section titled “GetQueueLimits”Read the live rate/concurrency configuration and saturation state.
{ cmd: 'GetQueueLimits', queue: string, maxJobs?: number }
{ ok: true, data: { limits: { rateLimit: { max: number, duration: number } | null, rateLimitTtl: number, // -2 when no rate limit exists concurrencyLimit: number | null, maxed: boolean } }}Job group controls and getters
Section titled “Job group controls and getters”Group depth excludes active jobs and includes waiting, prioritized and delayed
jobs. Every response below is wrapped in data:
{ cmd: 'GetGroupJobsCount', queue, groupId }// -> { ok: true, data: { count: number } }
{ cmd: 'GetGroupsJobsCount', queue, maxCount? }// -> { ok: true, data: { count: number } }
{ cmd: 'GetGroupActiveCount', queue, groupId }// -> { ok: true, data: { count: number } }
{ cmd: 'SetGroupRateLimit', queue, groupId, max, duration }{ cmd: 'GetGroupRateLimit', queue, groupId }// -> { ok: true, data: { limit: { max, duration } | null } }
{ cmd: 'RemoveGroupRateLimit', queue, groupId }// -> { ok: true, data: { removed: 0 | 1 } }
{ cmd: 'GetGroupRateLimitTtl', queue, groupId, maxJobs? }// -> { ok: true, data: { ttl: number } }
{ cmd: 'SetGroupConcurrency', queue, groupId, concurrency }{ cmd: 'GetGroupConcurrency', queue, groupId }// -> { ok: true, data: { concurrency: number | null } }
{ cmd: 'RemoveGroupConcurrency', queue, groupId }// -> { ok: true, data: { removed: 0 | 1 } }
{ cmd: 'PauseGroup', queue, groupId }// -> { ok: true, data: { changed: boolean } }{ cmd: 'ResumeGroup', queue, groupId }// -> { ok: true, data: { changed: boolean } }{ cmd: 'IsGroupPaused', queue, groupId }// -> { ok: true, data: { paused: boolean } }{ cmd: 'RateLimitGroup', queue, groupId, duration }// -> { ok: true }Group IDs are non-empty strings of at most 256 characters. max, duration,
and concurrency must be positive safe integers. Stored overrides affect a
claim only when PULL/PULLB carries the corresponding group default.
Pause blocks only new claims from that group. RateLimitGroup installs an
immediately effective manual deadline even when the Worker has no group-rate
default.
Deduplication Introspection
Section titled “Deduplication Introspection”{ cmd: 'GetDeduplicationJobId', queue: string, deduplicationId: string }// -> { ok: true, data: { jobId: string | null } }
{ cmd: 'RemoveDeduplicationKey', queue: string, deduplicationId: string }// -> { ok: true, data: { count: number } }
{ cmd: 'RemoveJobDeduplicationKey', id: string }// -> { ok: true, data: { removed: boolean } }The job-owned form removes a key only when the requested job is still its registered owner.
MoveToWaitingChildren
Section titled “MoveToWaitingChildren”{ cmd: 'MoveToWaitingChildren', id: string, token?: string }// -> { ok: true, data: { moved: true } }The job must be active. The transition releases its active resources and
persists the parked state. If the job has a lock, token must match it.
Queue Config Commands
Section titled “Queue Config Commands”SetStallConfig / GetStallConfig
Section titled “SetStallConfig / GetStallConfig”Per-queue stall detection configuration. Numeric fields: stallInterval, maxStalls, gracePeriod (numeric strings are coerced, non-numeric values are dropped).
Request:
{ cmd: 'SetStallConfig', queue: string, config: { stallInterval?: number, maxStalls?: number, gracePeriod?: number } }{ cmd: 'GetStallConfig', queue: string }Response: { ok: true } for set, { ok: true, config: {...} } for get.
SetDlqConfig / GetDlqConfig
Section titled “SetDlqConfig / GetDlqConfig”Per-queue DLQ configuration. Numeric fields: autoRetryInterval, maxAutoRetries, maxAge, maxEntries.
Request:
{ cmd: 'SetDlqConfig', queue: string, config: { autoRetry?: boolean, autoRetryInterval?: number, maxAutoRetries?: number, maxAge?: number | null, maxEntries?: number } }{ cmd: 'GetDlqConfig', queue: string }Response: { ok: true } for set, { ok: true, config: {...} } for get.