Scheduled jobs

Learn about scheduled work that runs on a cron expression.

Jobs run on a schedule. Each file is a separate job, with its own cron expression.

File location

Files at src/jobs/<name>.ts auto-register on the next deploy. The filename (without .ts) is the job name — lowercase, kebab-friendly. Each file exports a cron schedule string and an async run() function.

FileJob name
src/jobs/weekly-tax-report.tsweekly-tax-report
src/jobs/sync-balances.tssync-balances

Required exports

// src/jobs/weekly-tax-report.ts
import { Log } from "@backfill-io/sdk";

export const schedule = "0 8 * * 1";

export async function run() {
  // your work here
}
ExportTypeRequired
schedulestring (cron expression)yes
runasync functionyes
timezonestring (IANA tz, default "UTC")no
retrynumber (attempts, default 1)no
timeout_msnumber (default 30_000)no

Cron syntax

Standard 5-field cron (minute, hour, day-of-month, month, day-of-week). Invalid expressions fail at deploy:

src/jobs/weekly-tax-report.ts: invalid cron expression '0 8 ?'

Examples:

ExpressionMeaning
0 * * * *Top of every hour.
*/15 * * * *Every 15 minutes.
0 8 * * 18am every Monday.
0 0 1 * *Midnight on the 1st of every month.

Timezone

export const schedule = "0 9 * * 1-5";
export const timezone = "America/New_York";

Unknown zones are rejected at deploy. "UTC" and "Etc/UTC" are pre-accepted; everything else must be a recognized IANA name.

What the job can do

run() runs in a fresh sandbox context with the standard library: Entity queries, Http calls (against permitted hosts), Log, Settings, Secrets, and generated entity classes. Permissions are the manifest’s.

Manual trigger

backfill job run weekly-tax-report

For listing jobs:

backfill job list

Idempotency

A job that fails partway is not rolled back — anything you wrote to entities stays written. If your job is non-idempotent, structure it so a retry is safe (cursor-based pagination, idempotency keys on outbound calls, dedupe checks before creates).