Skip to content

Concurrency & Queues

Control how many task runs execute simultaneously.

Default Behavior

  • Each task gets its own queue by default
  • Unbounded concurrency — limited only by environment limits
  • Environment has a base limit and burstable limit (default 2× base)
  • Only actively executing runs count against concurrency

Setting Task Concurrency

ts
export const oneAtATime = task({
  id: "one-at-a-time",
  queue: { concurrencyLimit: 1 },
  run: async (payload) => { /* ... */ },
});

Sharing Queues Between Tasks

ts
import { queue, task } from "@trigger.dev/sdk";

export const myQueue = queue({
  name: "my-queue",
  concurrencyLimit: 1,
});

export const task1 = task({ id: "task-1", queue: myQueue, run: async (payload) => { /* ... */ } });
export const task2 = task({ id: "task-2", queue: myQueue, run: async (payload) => { /* ... */ } });
// Only one of task1 or task2 runs at a time

Override Queue at Trigger Time

ts
// Default: 1 at a time
const handle = await generatePullRequest.trigger(data);

// Priority: use a dedicated paid queue
const handle = await generatePullRequest.trigger(data, {
  queue: { name: "paid-users", concurrencyLimit: 10 },
});

Per-Tenant Queuing with concurrencyKey

Create a separate queue instance per user or organization:

ts
// Free users: 1 concurrent run per user
await generatePullRequest.trigger(data, {
  queue: "free-users",
  concurrencyKey: data.userId,
});

// Paid users: 10 concurrent runs per user
await generatePullRequest.trigger(data, {
  queue: "paid-users",
  concurrencyKey: data.userId,
});

Concurrency and Waits

When a task reaches a wait (triggerAndWait, wait.for, etc.) it releases its concurrency slot:

ts
export const parentTask = task({
  id: "parent-task",
  queue: { concurrencyLimit: 1 },
  run: async (payload) => {
    await subtask.triggerAndWait(payload);
    // Parent checkpointed here — releases slot
    // Another run of parentTask can now start!
  },
});

Subtasks and Queues

Subtasks do NOT inherit the parent's queue — they run on their own queue.

Managing Queues with the SDK

ts
import { queues } from "@trigger.dev/sdk";

// List queues
const allQueues = await queues.list();
const page = await queues.list({ page: 1, perPage: 20 });

// Retrieve a queue
const q1 = await queues.retrieve("queue_1234");
const q2 = await queues.retrieve({ type: "task", name: "my-task-id" });
const q3 = await queues.retrieve({ type: "custom", name: "my-custom-queue" });

// Queue object properties:
// id, name, type, running, queued, paused,
// concurrencyLimit, concurrency: { current, base, override }

// Pause / Resume
await queues.pause("queue_1234");
await queues.resume({ type: "task", name: "my-task-id" });

// Override concurrency
await queues.overrideConcurrencyLimit("queue_1234", 5);
await queues.overrideConcurrencyLimit({ type: "task", name: "my-task-id" }, 20);

// Reset to base
await queues.resetConcurrencyLimit("queue_1234");

Built from official Trigger.dev documentation