Use this skill when writing, designing, or optimizing Trigger.dev background tasks and workflows. This includes creating reliable async tasks, implementing AI workflows, setting up scheduled jobs, structuring complex task hierarchies with subtasks, configuring build extensions for tools like ffmpeg or Puppeteer/Playwright, and handling task schemas with Zod validation.
You are an expert Trigger.dev developer specializing in building production-grade background job systems. Tasks deployed to Trigger.dev run in Node.js 21+ and use the @trigger.dev/sdk package.
@trigger.dev/sdk - Never use @trigger.dev/sdk/v3 or deprecated client.defineJob patternnode-fetch - Use the built-in fetch functiontriggerAndWait, batchTriggerAndWait, and wait.* calls cannot be wrapped in Promise.all or Promise.allSettledimport { task } from "@trigger.dev/sdk";
export const processData = task({
id: "process-data",
retry: {
maxAttempts: 10,
factor: 1.8,
minTimeoutInMs: 500,
maxTimeoutInMs: 30_000,
},
run: async (payload: { userId: string; data: any[] }) => {
console.log(`Processing ${payload.data.length} items`);
return { processed: payload.data.length };
},
});
import { schemaTask } from "@trigger.dev/sdk";
import { z } from "zod";
export const validatedTask = schemaTask({
id: "validated-task",
schema: z.object({
name: z.string(),
email: z.string().email(),
}),
run: async (payload) => {
// Payload is automatically validated and typed
return { message: `Hello ${payload.name}` };
},
});
import { tasks } from "@trigger.dev/sdk";
import type { processData } from "./trigger/tasks";
const handle = await tasks.trigger<typeof processData>("process-data", {
userId: "123",
data: [{ id: 1 }],
});
export const parentTask = task({
id: "parent-task",
run: async (payload) => {
// Trigger and wait - returns Result object, NOT direct output
const result = await childTask.triggerAndWait({ data: "value" });
if (result.ok) {
console.log("Output:", result.output);
} else {
console.error("Failed:", result.error);
}
// Or unwrap directly (throws on error)
const output = await childTask.triggerAndWait({ data: "value" }).unwrap();
},
});
Always use idempotency keys when triggering tasks from inside other tasks:
import { idempotencyKeys } from "@trigger.dev/sdk";
export const paymentTask = task({
id: "process-payment",
run: async (payload: { orderId: string }) => {
// Scoped to current run - survives retries
const key = await idempotencyKeys.create(`payment-${payload.orderId}`);
await chargeCustomer.trigger(payload, {
idempotencyKey: key,
idempotencyKeyTTL: "24h",
});
},
});
await myTask.trigger(payload, {
delay: "1h", // Delay execution
ttl: "10m", // Cancel if not started within TTL
idempotencyKey: key,
queue: "my-queue",
machine: "large-1x", // micro, small-1x, small-2x, medium-1x, medium-2x, large-1x, large-2x
maxAttempts: 3,
tags: ["user_123"], // Max 10 tags
debounce: { // Consolidate rapid triggers
key: "unique-key",
delay: "5s",
mode: "trailing", // "leading" (default) or "trailing"
},
});
Consolidate multiple triggers into a single execution:
// Rapid triggers with same key = single execution
await myTask.trigger({ userId: "123" }, {
debounce: {
key: "user-123-update",
delay: "5s",
},
});
// Trailing mode: use payload from LAST trigger
await myTask.trigger({ data: "latest" }, {
debounce: {
key: "my-key",
delay: "10s",
mode: "trailing",
},
});
Use cases: user activity updates, webhook deduplication, search indexing, notification batching.
Up to 1,000 items per batch, 3MB per payload:
const results = await myTask.batchTriggerAndWait([
{ payload: { userId: "1" } },
{ payload: { userId: "2" } },
]);
for (const result of results) {
if (result.ok) console.log(result.output);
}
| Preset | vCPU | Memory |
|---|---|---|
| micro | 0.25 | 0.25GB |
| small-1x | 0.5 | 0.5GB |
| small-2x | 1 | 1GB |
| medium-1x | 1 | 2GB |
| medium-2x | 2 | 4GB |
| large-1x | 4 | 8GB |
| large-2x | 8 | 16GB |
Promise.allSettled inside a single task is better than many subtasks (each task has dedicated process and is charged by millisecond)maxAttempts based on the operationlogger.info(), logger.error(), etc.For detailed documentation on specific topics, read these files:
basic-tasks.md - Task basics, triggering, waitsadvanced-tasks.md - Tags, queues, concurrency, metadata, error handlingscheduled-tasks.md - Cron schedules, declarative and imperativerealtime.md - Real-time subscriptions, streams, React hooksconfig.md - trigger.config.ts, build extensions (Prisma, Playwright, FFmpeg, etc.)