Scheduled Tasks (Cron)
Scheduled tasks run on a recurring schedule defined by a cron expression. For one-off future triggers, use the delay option instead.
Defining a Scheduled Task
ts
import { schedules } from "@trigger.dev/sdk";
export const firstScheduledTask = schedules.task({
id: "first-scheduled-task",
run: async (payload) => {
console.log(payload.timestamp); // Date — when task was scheduled to run
console.log(payload.lastTimestamp); // Date or undefined — when last run
console.log(payload.timezone); // IANA format, e.g. "America/New_York"
console.log(payload.scheduleId); // string — the schedule id
console.log(payload.externalId); // string or undefined
console.log(payload.upcoming); // Date[] — next 5 scheduled dates
},
});WARNING
This task will NOT trigger on a schedule until you attach a schedule to it.
Attaching a Schedule
Two approaches:
| Method | Defined where | Synced when |
|---|---|---|
| Declarative | On the schedules.task | On dev or deploy |
| Imperative | Dashboard or SDK | At runtime |
Declarative Schedule
ts
export const firstScheduledTask = schedules.task({
id: "first-scheduled-task",
cron: "0 */2 * * *", // every 2 hours (UTC)
run: async (payload) => { /* ... */ },
});With timezone and environment targeting:
ts
export const secondScheduledTask = schedules.task({
id: "second-scheduled-task",
cron: {
pattern: "0 5 * * *", // 5am daily
timezone: "Asia/Tokyo",
environments: ["PRODUCTION", "STAGING"],
},
run: async (payload) => { /* ... */ },
});Imperative Schedule
ts
const createdSchedule = await schedules.create({
task: firstScheduledTask.id,
cron: "0 0 * * *",
timezone: "America/New_York",
externalId: "user_123456", // for multi-tenant schedules
deduplicationKey: "user_123456-reminder",
});Cron Syntax Reference
* * * * *
│ │ │ │ └── day of week (0-7, 1L-7L; 0 or 7 = Sunday)
│ │ │ └─────── month (1-12)
│ │ └──────────── day of month (1-31, L)
│ └───────────────── hour (0-23)
└────────────────────── minute (0-59)Lmeans "last" (e.g.,Lin day-of-month = last day of month)- Seconds are not supported
When Schedules Won't Trigger
- Dev environment — only triggers when the CLI dev server is running
- Staging/Production — only triggers if the task is in the current deployment (latest version)
Dynamic / Multi-Tenant Schedules
Use externalId to create per-user schedules:
ts
export const reminderTask = schedules.task({
id: "todo-reminder",
run: async (payload) => {
if (!payload.externalId) throw new Error("externalId required");
const user = await db.getUser(payload.externalId);
await sendReminderEmail(user);
},
});
// Create schedule per user
await schedules.create({
task: "todo-reminder",
cron: "0 9 * * 1", // 9am every Monday
externalId: userId,
deduplicationKey: `reminder-${userId}`,
});Always use deduplicationKey
When creating schedules dynamically, always include a deduplicationKey to prevent duplicates.
SDK Management Functions
ts
await schedules.retrieve(scheduleId) // Get a schedule
await schedules.list() // List all schedules
await schedules.update(scheduleId, options) // Update schedule
await schedules.deactivate(scheduleId) // Pause schedule
await schedules.activate(scheduleId) // Resume schedule
await schedules.del(scheduleId) // Delete schedule
await schedules.timezones() // Get valid IANA timezonesPlan Limits
| Tier | Max Schedules |
|---|---|
| Free | 10 per project |
| Hobby | 100 per project |
| Pro | 1,000+ per project |
Extra bundles: $10/month per 1,000 schedules.