Skip to main content
When you trigger a task, the run is placed into a queue. Trigger.dev then picks runs off the queue and executes them according to the concurrency limits you configure. By default each task gets its own queue with no concurrency limit other than the overall limit for your environment. Only actively executing runs count towards concurrency — runs that are waiting at a waitpoint release their slot until they resume.

Default concurrency

All tasks start with an unbounded concurrency limit, capped by your environment’s overall limit.
Environments have a base concurrency limit and a burstable limit (default burst factor: 2x the base limit). Individual queues are limited by the base limit, not the burstable limit. For example, if your base limit is 10, the environment can burst to 20 concurrent runs, but any single queue can have at most 10 concurrent runs at once.

Setting task concurrency

Limit how many runs of a task can execute simultaneously using queue.concurrencyLimit:
/trigger/one-at-a-time.ts
This is useful when you need to control access to a shared resource like a database or an API with rate limits.

Sharing concurrency between tasks

Define a named queue and assign it to multiple tasks. All tasks sharing the queue will respect the same concurrency limit:
/trigger/queue.ts
In this example, task1 and task2 share the same queue, so only one of them can run at a time across both tasks.

Overriding the queue at trigger time

You can override the default queue when triggering a run. This is useful for high-priority runs that need more concurrency:
/trigger/override-concurrency.ts
app/api/push/route.ts

Per-tenant queuing with concurrencyKey

Use concurrencyKey to create a separate queue for each unique value. This is useful when you want isolated concurrency limits per user, organization, or any other entity:
app/api/pr/route.ts

Concurrency and waits

When a run reaches a waitpoint (such as wait.for(), triggerAndWait(), or wait.forToken()), it is checkpointed and transitions to a WAITING state. At this point, the run releases its concurrency slot back to the queue and environment. This means:
  • Only actively executing runs count towards concurrency limits.
  • Runs in the WAITING state do not hold a slot — you can have far more waiting runs than your concurrency limit.
  • When a waiting run resumes, it must re-acquire a slot before continuing.

Parent and subtask concurrency

When a parent task triggers and waits for a subtask on a different queue, the parent checkpoints and releases its slot. This prevents deadlocks:
/trigger/waiting.ts

Managing queues with the SDK

Import the queues namespace to manage queues programmatically:

Listing queues

Retrieving a queue

The returned queue object includes:

Pausing and resuming queues

Pausing a queue prevents new runs from starting. Currently executing runs continue to completion.

Overriding concurrency limits

Temporarily change a queue’s concurrency limit at runtime: