Cron
Deno.cron() is a Deno runtime API for scheduling JavaScript or TypeScript code to run on a recurring schedule, expressed using cron syntax. It ships with Deno itself, so the same code that runs locally can be deployed without changes.
Deno.cron is currently an unstable API. To use it locally with deno run, enable the --unstable-cron flag (or add "cron" to the unstable array in deno.json).
deno run --unstable-cron main.ts
Defining a cron job
Deno.cron() takes a human-readable name, a schedule, and a handler function. The name identifies the cron job in logs, the schedule determines when the handler fires, and all times are in UTC.
Deno.cron("log-a-message", "* * * * *", () => {
console.log("This runs once a minute.");
});
A 5-field cron expression has one field per time unit, separated by spaces:
┌──────────── minute (0-59)
│ ┌────────── hour (0-23)
│ │ ┌──────── day of month (1-31)
│ │ │ ┌────── month (1-12 or JAN-DEC)
│ │ │ │ ┌──── day of week (0-6 or SUN-SAT, where 0 is Sunday)
│ │ │ │ │
* * * * *
Each field accepts an exact value, * (every value), a range (1-5), a list (1,3,5), or a step (*/15 for every fifteenth unit). For example, 0 9 * * MON-FRI runs at 09:00 UTC on weekdays.
The schedule can be a standard 5-field cron expression or a structured object:
Deno.cron("hourly-task", { hour: { every: 1 } }, () => {
console.log("This runs once an hour.");
});
Cron jobs must be registered at the top level of a module, before any server starts. Definitions nested inside request handlers, conditionals, or callbacks will not be picked up.
Retries and backoff
By default, failed handler invocations are not retried. Pass a backoffSchedule (an array of millisecond delays) to retry on failure:
Deno.cron(
"retry-example",
"* * * * *",
{ backoffSchedule: [1000, 5000, 10000] },
() => {
throw new Error("Will be retried up to three times.");
},
);
Running cron jobs in production
Deno.cron keeps execution state in-memory in the Deno CLI, which means each process maintains its own independent set of cron tasks. For production workloads, Deno Deploy builds on top of this runtime API: it discovers your Deno.cron() definitions at deployment time, schedules and invokes them, handles retries, and surfaces runs in a dashboard — so you don't need to keep a long-running process up yourself.
OpenTelemetry
When OpenTelemetry is enabled (OTEL_DENO=true), each Deno.cron() invocation automatically produces an OpenTelemetry span. This lets you trace cron execution alongside your other instrumented code:
OTEL_DENO=true deno run --unstable-cron main.ts
Each cron invocation creates a span named after the cron job. The span covers the duration of the handler function, and any spans created inside the handler are nested under it as children.
Last updated on
© 2018–2025 the Deno authors
Licensed under the MIT License.
https://docs.deno.com/runtime/fundamentals/cron