When you trigger a task from your backend code, you need to set the TRIGGER_SECRET_KEY environment variable. You can find the value on the API keys page in the Trigger.dev dashboard. More info on API keys.
Triggers a single run of a task with the payload you pass in, and any options you specify. It does NOT wait for the result, you cannot do that from outside a task.
import { emailSequence } from "~/trigger/emails";//app/email/route.tsexport async function POST(request: Request) { //get the JSON from the request const data = await request.json(); //trigger your task const handle = await emailSequence.trigger({ to: data.email, name: data.name }); //return a success response with the handle return Response.json(handle);}
import { emailSequence } from "~/trigger/emails";export async function action({ request, params }: ActionFunctionArgs) { if (request.method.toUpperCase() !== "POST") { return json("Method Not Allowed", { status: 405 }); } //get the JSON from the request const data = await request.json(); //trigger your task const handle = await emailSequence.trigger({ to: data.email, name: data.name }); //return a success response with the handle return json(handle);}
Triggers multiples runs of a task with the payloads you pass in, and any options you specify. It does NOT wait for the results, you cannot do that from outside a task.
import { emailSequence } from "~/trigger/emails";//app/email/route.tsexport async function POST(request: Request) { //get the JSON from the request const data = await request.json(); //batch trigger your task const batchHandle = await emailSequence.batchTrigger( data.users.map((u) => ({ payload: { to: u.email, name: u.name } })) ); //return a success response with the handle return Response.json(batchHandle);}
import { emailSequence } from "~/trigger/emails";export async function action({ request, params }: ActionFunctionArgs) { if (request.method.toUpperCase() !== "POST") { return json("Method Not Allowed", { status: 405 }); } //get the JSON from the request const data = await request.json(); //batch trigger your task const batchHandle = await emailSequence.batchTrigger( data.users.map((u) => ({ payload: { to: u.email, name: u.name } })) ); //return a success response with the handle return json(batchHandle);}
You can trigger tasks from other tasks using trigger() or batchTrigger(). You can also trigger and wait for the result of triggered tasks using triggerAndWait() and batchTriggerAndWait(). This is a powerful way to build complex tasks.
This is where it gets interesting. You can trigger a task and then wait for the result. This is useful when you need to call a different task and then use the result to continue with your task.
Don't use this in parallel, e.g. with `Promise.all()`
Instead, use batchTriggerAndWait() if you can, or a for loop if you can’t.To control concurrency using batch triggers, you can set queue.concurrencyLimit on the child task.
export const loopTask = task({ id: "loop-task", run: async (payload: string) => { //this will be slower than the batch version //as we have to resume the parent after each iteration for (let i = 0; i < 2; i++) { const result = await childTask.triggerAndWait(`item${i}`); console.log("Result", result); //...do stuff with the result } },});
/trigger/parent.ts
export const parentTask = task({ id: "parent-task", run: async (payload: string) => { const result = await batchChildTask.triggerAndWait("some-data"); console.log("Result", result); //...do stuff with the result },});
You can batch trigger a task and wait for all the results. This is useful for the fan-out pattern, where you need to call a task multiple times and then wait for all the results to continue with your task.
Don't use this in parallel, e.g. with `Promise.all()`
Instead, pass in all items at once and set an appropriate maxConcurrency. Alternatively, use sequentially with a for loop.To control concurrency, you can set queue.concurrencyLimit on the child task.
export const loopTask = task({ id: "loop-task", run: async (payload: string) => { //this will be slower than a single batchTriggerAndWait() //as we have to resume the parent after each iteration for (let i = 0; i < 2; i++) { const result = await childTask.batchTriggerAndWait([ { payload: `itemA${i}` }, { payload: `itemB${i}` }, ]); console.log("Result", result); //...do stuff with the result } },});
Server Actions allow you to call your backend code without creating API routes. This is very useful for triggering tasks but you need to be careful you don’t accidentally bundle the Trigger.dev SDK into your frontend code.If you see an error like this then you’ve bundled @trigger.dev/sdk into your frontend code:
Module build failed: UnhandledSchemeError: Reading from "node:crypto" is not handled by plugins (Unhandled scheme).Module build failed: UnhandledSchemeError: Reading from "node:process" is not handled by plugins (Unhandled scheme).Webpack supports "data:" and "file:" URIs by default.You may need an additional plugin to handle "node:" URIs.
When you use server actions that use @trigger.dev/sdk:
The file can’t have any React components in it.
The file should have "use server" on the first line.
Here’s an example of how to do it with a component that calls the server action and the actions file: