Skip to main content
Scheduled tasks are for recurring work. To trigger a one-off task at a future time, use the delay option when triggering.

Defining a scheduled task

Use schedules.task() to define a task that runs on a schedule. The payload argument contains useful properties about the current invocation:
/trigger/first-scheduled-task.ts
import { schedules } from "@trigger.dev/sdk";

export const firstScheduledTask = schedules.task({
  id: "first-scheduled-task",
  run: async (payload) => {
    // The time this task was scheduled to run
    console.log(payload.timestamp); // Date object

    // The last time this task ran (undefined if it has never run)
    console.log(payload.lastTimestamp); // Date | undefined

    // The IANA timezone the schedule was created with, e.g. "America/New_York"
    console.log(payload.timezone); // string, defaults to "UTC"

    // Format the scheduled time in the schedule's timezone
    const formatted = payload.timestamp.toLocaleString("en-US", {
      timeZone: payload.timezone,
    });
    console.log(formatted);

    // The ID of the schedule that triggered this run
    console.log(payload.scheduleId); // string

    // An optional external ID you set when creating the schedule (e.g. a userId)
    console.log(payload.externalId); // string | undefined

    // The next 5 times this task is scheduled to run
    console.log(payload.upcoming); // Date[]
  },
});
The payload fields are:
FieldTypeDescription
timestampDateThe time the task was scheduled to run (UTC).
lastTimestampDate | undefinedThe last time the task ran.
timezonestringIANA timezone of the schedule, e.g. "UTC" or "America/New_York".
scheduleIdstringThe ID of the schedule that triggered this run.
externalIdstring | undefinedAn optional external ID set when creating the schedule.
upcomingDate[]The next 5 scheduled run times.
This task will not run on a schedule until you attach at least one schedule to it.

How to attach a schedule

There are two ways to attach a schedule to a schedules.task():
  • Declarative — defined directly on the task. Synced automatically when you run dev or deploy.
  • Imperative — created from the dashboard or via SDK functions like schedules.create().
A single scheduled task can have multiple schedules attached — a declarative one and/or many imperative ones.

Declarative schedules

Add a cron property to your schedules.task(). This is synced when you run the dev or deploy commands. A string value runs in UTC:
/trigger/every-two-hours.ts
import { schedules } from "@trigger.dev/sdk";

export const everyTwoHours = schedules.task({
  id: "every-two-hours",
  // Runs every two hours in UTC
  cron: "0 */2 * * *",
  run: async (payload) => {
    // ...
  },
});
To specify a timezone, use the object form:
/trigger/daily-tokyo.ts
import { schedules } from "@trigger.dev/sdk";

export const dailyTokyo = schedules.task({
  id: "daily-tokyo",
  cron: {
    // 5am every day Tokyo time
    pattern: "0 5 * * *",
    timezone: "Asia/Tokyo",
    // Optional: restrict which environments this schedule applies to
    // Possible values: "PRODUCTION", "STAGING", "PREVIEW", "DEVELOPMENT"
    environments: ["PRODUCTION", "STAGING"],
  },
  run: async (payload) => {
    // ...
  },
});

Imperative schedules

Create schedules dynamically at runtime using schedules.create(). Imperative schedules can be created, updated, activated, deactivated, and deleted without redeploying code. This is useful when each of your users needs their own schedule:
/trigger/reminder.ts
import { schedules } from "@trigger.dev/sdk";

export const reminderTask = schedules.task({
  id: "todo-reminder",
  run: async (payload) => {
    if (!payload.externalId) {
      throw new Error("externalId is required");
    }

    // Use the externalId to look up the user
    const user = await db.getUser(payload.externalId);
    await sendReminderEmail(user);
  },
});
Create a schedule for each user from your backend:
Next.js API route
import { schedules } from "@trigger.dev/sdk";
import { reminderTask } from "~/trigger/reminder";

export async function POST(request: Request) {
  const data = await request.json();

  const createdSchedule = await schedules.create({
    task: reminderTask.id,
    cron: "0 8 * * *", // 8am every day
    timezone: data.timezone,
    externalId: data.userId,
    // Prevents duplicate schedules for the same user
    deduplicationKey: `${data.userId}-reminder`,
  });

  return Response.json(createdSchedule);
}

Supported cron syntax

*    *    *    *    *
┬    ┬    ┬    ┬    ┬
│    │    │    │    │
│    │    │    │    └ day of week (0 - 7, 1L - 7L) (0 or 7 is Sun)
│    │    │    └───── month (1 - 12)
│    │    └────────── day of month (1 - 31, L)
│    └─────────────── hour (0 - 23)
└──────────────────── minute (0 - 59)
L means “last”. In the day-of-week field, 1L means the last Monday of the month. In the day-of-month field, L means the last day of the month.
Seconds are not supported in the cron syntax.

When schedules will not trigger

  • Development environment — scheduled tasks only trigger while the dev CLI is running.
  • Production/Staging — scheduled tasks only trigger for the current deployment. Tasks from previous deployments are not triggered.

Attaching schedules in the dashboard

1

Go to the Schedules page

In the sidebar, select the Schedules page, then press New schedule.
2

Create your schedule

Fill in the form and press Create schedule.
FieldDescription
TaskThe ID of the task to attach the schedule to.
Cron patternThe schedule in cron format.
TimezoneThe timezone the schedule runs in. Defaults to UTC.
External IDAn optional external ID, e.g. a user ID.
Deduplication keyIf you pass the same key again, the schedule is updated instead of duplicated.
EnvironmentsThe environments this schedule applies to.

Attaching schedules with the SDK

schedules.create()

import { schedules } from "@trigger.dev/sdk";
import { firstScheduledTask } from "~/trigger/first-scheduled-task";

const createdSchedule = await schedules.create({
  task: firstScheduledTask.id,
  cron: "0 0 * * *",
  // Optional IANA timezone. Automatically adjusts for DST.
  timezone: "America/New_York",
  // Optional external ID (e.g. a user ID)
  externalId: "user_123456",
  // Prevents duplicate schedules. Updating uses the same key.
  deduplicationKey: "user_123456-todo_reminder",
});

Managing schedules with the SDK

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

const schedule = await schedules.retrieve(scheduleId);

Testing scheduled tasks

You can trigger a scheduled task from the Test page in the dashboard. The scheduleId will always be sched_1234 in a test run.
1

Go to the Test page

In the sidebar, select Test, then choose a scheduled task from the list (they have a clock icon).
2

Fill in the form and run

Set the timestamp and any other fields, then press Run test. You can also select from a recent run to pre-populate the form.

Build docs developers (and LLMs) love