Waiting allows you to write complex tasks as straightforward async code. A waiting task releases its compute slot and only resumes when ready — you are not charged for idle time above 5 seconds.
| Function | What it does |
|---|
wait.for() | Waits for a specific duration, e.g. 1 day. |
wait.until() | Waits until a specific Date. |
wait.forToken() | Pauses a run until an external token is completed. |
All wait functions must be called from inside a task.run() block. They will throw if called
outside one.
wait.for()
Pause execution for a fixed duration. Supported units: seconds, minutes, hours, days, weeks, months, years.
/trigger/wait-for-example.ts
import { task, wait } from "@trigger.dev/sdk";
export const waitForExample = task({
id: "wait-for-example",
run: async (payload: { message: string }) => {
console.log("Starting...");
await wait.for({ seconds: 30 });
await wait.for({ minutes: 5 });
await wait.for({ hours: 2 });
await wait.for({ days: 1 });
await wait.for({ weeks: 1 });
console.log("Resuming after wait.");
},
});
Waits of 5 seconds or less count towards compute usage because the task does not checkpoint — it
stays resident in memory.
Idempotency
Use idempotencyKey to ensure a wait is only registered once if the task retries:
import { task, wait } from "@trigger.dev/sdk";
export const idempotentWait = task({
id: "idempotent-wait",
run: async (payload: any) => {
// Even if this task retries, the wait is only registered once
await wait.for({ hours: 1 }, { idempotencyKey: "my-unique-wait-key" });
},
});
wait.until()
Pause execution until a specific Date:
/trigger/wait-until-example.ts
import { task, wait } from "@trigger.dev/sdk";
export const waitUntilExample = task({
id: "wait-until-example",
run: async (payload: { resumeAt: string }) => {
const resumeDate = new Date(payload.resumeAt);
// Wait until a specific date
await wait.until({ date: resumeDate });
console.log("Resumed at", new Date().toISOString());
},
});
Pass throwIfInThePast: true to throw an error if the date has already passed:
await wait.until({ date: new Date("2025-01-01"), throwIfInThePast: true });
wait.forToken()
Pause a run until an external event completes a token. This is useful for human-in-the-loop workflows, webhooks from third-party services, or any external approval step.
How it works
Create a token
Inside your task, create a waitpoint token. The token has a URL that can be called to complete it./trigger/approval-task.ts
import { task, wait } from "@trigger.dev/sdk";
export const approvalTask = task({
id: "approval-task",
run: async (payload: { documentId: string }) => {
const token = await wait.createToken({
// Prevent duplicate tokens if the task retries
idempotencyKey: `approve-document-${payload.documentId}`,
// Automatically complete the token as failed after this duration
timeout: "24h",
tags: [`document-${payload.documentId}`],
});
// Send the token URL to an external system or a human reviewer
await sendReviewEmail({
documentId: payload.documentId,
approvalUrl: token.url,
});
// Pause until the token is completed or times out
const result = await wait.forToken<{ approved: boolean; comment: string }>(token);
if (!result.ok) {
// Token timed out
throw result.error;
}
return result.output; // { approved: boolean, comment: string }
},
});
Complete the token
From anywhere in your codebase — or via HTTP callback — complete the token with a result:import { wait } from "@trigger.dev/sdk";
// Complete the token with data
await wait.completeToken(token.id, {
approved: true,
comment: "Looks good!",
});
Or POST JSON to the token URL directly (useful for webhooks):curl -X POST https://trigger.dev/api/v1/waitpoints/tokens/<TOKEN_ID>/complete \
-H "Content-Type: application/json" \
-d '{"approved": true, "comment": "Looks good!"}'
Using wait.forToken() with webhooks
This pattern is ideal for integrating with services that support webhooks:
/trigger/replicate-task.ts
import { task, wait } from "@trigger.dev/sdk";
import Replicate from "replicate";
const replicate = new Replicate({ auth: process.env.REPLICATE_API_TOKEN });
export const replicateTask = task({
id: "replicate-prediction",
run: async (payload: { prompt: string }) => {
const token = await wait.createToken({
timeout: "10m",
tags: ["replicate"],
});
// Pass the token URL as the webhook — Replicate will POST results to it
await replicate.predictions.create({
version: "27b93a2413e7f36cd83da926f3656280b2931564ff050bf9575f1fdf9bcd7478",
input: {
prompt: payload.prompt,
},
webhook: token.url,
webhook_events_filter: ["completed"],
});
// Pause until Replicate posts the result back
const prediction = await wait.forToken(token).unwrap();
return prediction;
},
});
Managing tokens
import { wait } from "@trigger.dev/sdk";
// Retrieve a token
const token = await wait.retrieveToken(tokenId);
// List tokens (supports async iteration)
for await (const token of wait.listTokens()) {
console.log("Token ID:", token.id);
}
// Complete a token
await wait.completeToken(tokenId, { result: "approved" });
Lifecycle hooks during waits
Use onWait and onResume hooks to run code when a task pauses or resumes. This is useful for managing resources like database connections:
import { task, wait } from "@trigger.dev/sdk";
export const dbTask = task({
id: "db-task",
onWait: async () => {
// Release the database connection when pausing
await db.disconnect();
},
onResume: async () => {
// Reconnect when resuming
await db.connect();
},
run: async (payload: any) => {
await db.connect();
// Do some work...
// The task checkpoints here, releasing its compute slot
await wait.for({ hours: 1 });
// Task resumes here after 1 hour
await db.query("SELECT 1");
},
});