Best Practices#

Small habits that keep scheduled jobs reliable. Most of these come down to the same idea that shapes GearTrain itself: keep it simple.

Keep Jobs Small#

A job should do one thing. A job that fetches, transforms, stores, and notifies is four jobs that fail together; split it and each piece is easy to run, read, and fix. When one part needs to happen more often than another, separate jobs let you give each its own schedule.

Simplicity also keeps runs inside their time and memory limits; see Limits.

Handle Errors#

An uncaught error fails the run and marks it Error in the history, which is exactly what you want for unexpected situations. Handle only the errors you can do something about:

// sync.js
import env from "env";

const res = await fetch("https://api.example.com/sync", {
    headers: { Authorization: `Bearer ${env.get("API_KEY")}` },
});

if (!res.ok) {
    // The API responded; the message may say why.
    throw new Error(`Sync failed: ${res.status} ${await res.text()}`);
}
  • Let real failures throw. A failed run in the history is a signal; a script that logs the failure and “succeeds” hides it.
  • Log context before throwing. Include the status code, the URL, or the file name in the message. See Running and Debugging.
  • Catch only what you can fix. A retry loop for a flaky endpoint is fine; swallowing every error with an empty catch is not.

Test With Manual Runs#

Before a schedule ever fires, exercise the script yourself: save it in the workbench and use the Run now panel, with per-run environment variables if it needs them. Watch the console, fix what breaks, and repeat until a run comes back clean. See Secrets and Environment Variables.

Then create the job with a schedule and check its first scheduled runs in the history.

Keep Secrets Out of Scripts#

Never hardcode credentials in a script. Anyone who can read the script can read the secret, and changing a key means editing every script that copies it. Store credentials as saved secrets and read them with env.get: the script stays shareable and the key rotates in one place. See Secrets and Environment Variables.

The same goes for logging: log an identifier, never the credential; console output is kept in the run history.

Expect the Clock#

Schedules drift around real-world events. A job that runs hourly will occasionally start a little late, and a failed run is retried after a short backoff before it is marked as failed. A job does not overlap itself: while a run or its retry is in progress, the next scheduled occurrence is skipped. See Retries and Failure Handling. Account-wide, only so many of your jobs run at once (see Limits); keeping runs short frees a turn for the next job quickly. Avoid logic that assumes exact timing. “Every run covers the last hour” breaks when a run is delayed or skipped; “every run covers everything not yet processed” does not care.