Default concurrency
By default, all tasks have an unbounded concurrency limit, limited only by the overall concurrency limits of your environment.Your environment has a base concurrency limit and a burstable limit (default burst factor of 2.0x
the base limit). Individual queues are limited by the base concurrency limit, not the burstable
limit. For example, if your base limit is 10, your environment can burst up to 20 concurrent runs,
but any single queue can have at most 10 concurrent runs. If you’re a paying customer you can
request higher burst limits by contacting us.
Setting task concurrency
You can set the concurrency limit for a task by setting theconcurrencyLimit
property on the task’s queue. This limits the number of runs that can be executing at any one time:
/trigger/one-at-a-time.ts
Sharing concurrency between tasks
As well as putting queue settings directly on a task, you can define a queue and reuse it across multiple tasks. This allows you to share the same concurrency limit:/trigger/queue.ts
task1
and task2
share the same queue, so only one of them can run at a time.
Setting the queue when you trigger a run
When you trigger a task you can override the default queue. This is really useful if you sometimes have high priority runs. The task and queue definition:/trigger/override-concurrency.ts
app/api/push/route.ts
Concurrency keys and per-tenant queuing
If you’re building an application where you want to run tasks for your users, you might want a separate queue for each of your users (or orgs, projects, etc.). You can do this by usingconcurrencyKey
. It creates a copy of the queue for each unique value of the key.
Your backend code:
app/api/pr/route.ts
Concurrency and subtasks
When you trigger a task that has subtasks, the subtasks will not inherit the queue from the parent task. Unless otherwise specified, subtasks will run on their own queue/trigger/subtasks.ts
Waits and concurrency
With our task checkpoint system, tasks can wait at various waitpoints (like waiting for subtasks to complete, delays, or external events). The way this system interacts with the concurrency system is important to understand. Concurrency is only released when a run reaches a waitpoint and is checkpointed. When a run is checkpointed, it transitions to theWAITING
state and releases its concurrency slot back to both the queue and the environment, allowing other runs to execute or resume.
This means that:
- Only actively executing runs count towards concurrency limits
- Runs in the
WAITING
state (checkpointed at waitpoints) do not consume concurrency slots - You can have more runs in the
WAITING
state than your queue’s concurrency limit - When a waiting run resumes (e.g., when a subtask completes), it must re-acquire a concurrency slot
concurrencyLimit
of 1:
- You can only have exactly 1 run executing at a time
- You may have multiple runs in the
WAITING
state that belong to that queue - When the executing run reaches a waitpoint and checkpoints, it releases its slot
- The next queued run can then begin execution
Waiting for a subtask on a different queue
When a parent task triggers and waits for a subtask on a different queue, the parent task will checkpoint and release its concurrency slot once it reaches the wait point. This prevents environment deadlocks where all concurrency slots would be occupied by waiting tasks./trigger/waiting.ts
triggerAndWait
call, it checkpoints and transitions to the WAITING
state, releasing its concurrency slot back to both its queue and the environment. Once the subtask completes, the parent task will resume and re-acquire a concurrency slot.