Skip to main content
Scheduled tasks are only for recurring tasks. If you want to trigger a one-off task at a future time, you should use the delay option.

Defining a scheduled task

This task will run when any of the attached schedules trigger. They have a predefined payload with some useful properties:
import { schedules } from "@trigger.dev/sdk";

export const firstScheduledTask = schedules.task({
  id: "first-scheduled-task",
  run: async (payload) => {
    //when the task was scheduled to run
    //note this will be slightly different from new Date() because it takes a few ms to run the task
    console.log(payload.timestamp); //is a Date object

    //when the task was last run
    //this can be undefined if it's never been run
    console.log(payload.lastTimestamp); //is a Date object or undefined

    //the timezone the schedule was registered with, defaults to "UTC"
    //this is in IANA format, e.g. "America/New_York"
    //See the full list here: https://cloud.trigger.dev/timezones
    console.log(payload.timezone); //is a string

    //If you want to output the time in the user's timezone do this:
    const formatted = payload.timestamp.toLocaleString("en-US", {
      timeZone: payload.timezone,
    });

    //the schedule id (you can have many schedules for the same task)
    //using this you can remove the schedule, update it, etc
    console.log(payload.scheduleId); //is a string

    //you can optionally provide an external id when creating the schedule
    //usually you would set this to a userId or some other unique identifier
    //this can be undefined if you didn't provide one
    console.log(payload.externalId); //is a string or undefined

    //the next 5 dates this task is scheduled to run
    console.log(payload.upcoming); //is an array of Date objects
  },
});
You can see from the comments that the payload has several useful properties:
  • timestamp - the time the task was scheduled to run, as a UTC date.
  • lastTimestamp - the time the task was last run, as a UTC date.
  • timezone - the timezone the schedule was registered with, defaults to “UTC”. In IANA format, e.g. “America/New_York”.
  • scheduleId - the id of the schedule that triggered the task
  • externalId - the external id you (optionally) provided when creating the schedule
  • upcoming - the next 5 times the task is scheduled to run
This task will NOT get triggered on a schedule until you attach a schedule to it. Read on for how to do that.
Like all tasks they don’t have timeouts, they should be placed inside a /trigger folder, and you can configure them.

How to attach a schedule

Now that we’ve defined a scheduled task, we need to define when it will actually run. To do this we need to attach one or more schedules. There are two ways of doing this:
  • Declarative: defined on your schedules.task. They sync when you run the dev command or deploy.
  • Imperative: created from the dashboard or by using the imperative SDK functions like schedules.create().
A scheduled task can have multiple schedules attached to it, including a declarative schedule and/or many imperative schedules.

Declarative schedules

These sync when you run the dev or deploy commands. To create them you add the cron property to your schedules.task(). This property is optional and is only used if you want to add a declarative schedule to your task:
export const firstScheduledTask = schedules.task({
  id: "first-scheduled-task",
  //every two hours (UTC timezone)
  cron: "0 */2 * * *",
  run: async (payload, { ctx }) => {
    //do something
  },
});
If you use a string it will be in UTC. Alternatively, you can specify a timezone like this:
export const secondScheduledTask = schedules.task({
  id: "second-scheduled-task",
  cron: {
    //5am every day Tokyo time
    pattern: "0 5 * * *",
    timezone: "Asia/Tokyo",
    //optional, defaults to all environments
    //possible values are "PRODUCTION", "STAGING", "PREVIEW" and "DEVELOPMENT"
    environments: ["PRODUCTION", "STAGING"],
  },
  run: async (payload) => {},
});
When you run the dev or deploy commands, declarative schedules will be synced. If you add, delete or edit the cron property it will be updated when you run these commands. You can view your schedules on the Schedules page in the dashboard.

Imperative schedules

Alternatively you can explicitly attach schedules to a schedules.task. You can do this in the Schedules page in the dashboard by just pressing the “New schedule” button, or you can use the SDK to create schedules. The advantage of imperative schedules is that they can be created dynamically, for example, you could create a schedule for each user in your database. They can also be activated, disabled, edited, and deleted without deploying new code by using the SDK or dashboard. To use imperative schedules you need to do two things:
  1. Define a task in your code using schedules.task().
  2. Attach 1+ schedules to the task either using the dashboard or the SDK.

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 the 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. We do not support seconds in the cron syntax.

When schedules won’t trigger

There are two situations when a scheduled task won’t trigger:
  • For Dev environments scheduled tasks will only trigger if you’re running the dev CLI.
  • For Staging/Production environments scheduled tasks will only trigger if the task is in the current deployment (latest version). We won’t trigger tasks from previous deployments.

Attaching schedules in the dashboard

You need to attach a schedule to a task before it will run on a schedule. You can attach static schedules in the dashboard:
1

Go to the Schedules page

In the sidebar select the “Schedules” page, then press the “New schedule” button. Or you can follow the onboarding and press the create in dashboard button.