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
.jsname, such asreports/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
awaitworks. Use it forfetch, file operations, and anything asynchronous, without wrapping your code in a main function. consoleoutput is captured. Everything you log withconsole.log,console.info,console.warn, orconsole.errorshows 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
.jsfiles 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.