Writing Jobs#

A job is a script plus a schedule. This guide covers the script side: where scripts live, what they look like, and how to describe a schedule with a cron expression.

Scripts Live in the Workbench#

The Workbench is the built-in editor for your files. Your account has a persistent file system, and the workbench manages the files in it:

  • Add File creates a new file. Give scripts a .js name, such as reports/daily-summary.js; data files, config files, and anything else are welcome too.
  • Add Folder creates a directory, so you can group files by project.
  • Save writes your changes. The file is saved to your file system immediately. There is no separate deploy step.
  • Rename and Delete sit in the file header, next to the file name: Rename and Delete.

You can also upload existing files. A job can point at any .js file in your file system, so reorganizing files never breaks anything as long as the path you pick still exists.

Anatomy of a Script#

A script is a single JavaScript file. It imports what it needs, and the top-level code, which runs once per run from top to bottom, is your job:

// cleanup.js
import fs from "fs";

let removed = 0;
for await (const entry of fs.readDir("/tmp/cache")) {
    await fs.remove(`/tmp/cache/${entry.name}`);
    removed++;
}

console.log(`Removed ${removed} files`);

Three things worth knowing:

  • Top-level await works. Use it for fetch, file operations, and anything asynchronous, without wrapping your code in a main function.
  • console output is captured. Everything you log with console.log, console.info, console.warn, or console.error shows up in the run’s live console. See Running and Debugging.
  • Scripts can import your files. Import the built-in modules by name, and your own .js files with relative paths: ./ is the script’s own directory, ../ its parent. Shared helpers belong in their own files:
// reports/daily.js
import { formatDate } from "./format.js";
import { sendReport } from "../lib/email.js";

See The Sandbox for the full picture.

Scheduling With Cron#

Jobs are scheduled with a cron expression: five fields separated by spaces, describing minutes, hours, days of the month, months, and days of the week.

Field Allowed values Special characters
Minute 0–59 * , - /
Hour 0–23 * , - /
Day of month 1–31 * , - /
Month 1–12 or JAN–DEC * , - /
Day of week 0–7 or SUN–SAT * , - /

Common schedules:

Expression Meaning
*/15 * * * * Every 15 minutes
0 * * * * Every hour, on the hour
0 3 * * * Every day at 03:00
0 9 * * 1 Every Monday at 09:00
0 0 1 * * At midnight on the 1st of every month

The free plan allows a job to run at most once every 15 minutes, so the fastest schedule is */15 * * * *. The job form shows a */15 * * * * placeholder as a reminder of the format. To experiment with expressions, crontab.guru translates any cron expression into plain English.

Managing Jobs#

Each job on the Jobs page has controls for its whole life cycle:

  • Run now starts a run immediately, without waiting for the schedule.
  • Pause stops scheduled runs. The job and its history stay intact, and Resume turns the schedule back on.
  • Edit changes the name, schedule, or script.
  • Delete removes the job. Its run history remains under Runs until you delete it there.

The job’s edit page also sets how failures are handled: how many times a scheduled run is attempted, whether to email you when it fails, and whether to pause the schedule after repeated failures. See Retries and Failure Handling.

Schedules are evaluated on the server, so jobs run on time whether or not you have the site open.