Cron jobs
Put scheduled jobs in crons/. Each file declares a cron expression and a handler, and the SDK sets up the schedule when you deploy.
On this pageWrite a scheduled job · Test it locally · Know how jobs behave after deploy
Job files
This step creates a job. Add a file under crons/**/*.ts. .mts, .js and .mjs also work.
Each job file must export:
export const cron = "<expression>"(or an array of expressions)- a default handler (recommended: wrapped with
defineScheduled)
Example:
// crons/hourly-heartbeat.ts
import { defineScheduled } from 'void';
export const cron = '0 * * * *';
export default defineScheduled(async (controller, env) => {
await env.KV.put('jobs:last-heartbeat', controller.scheduledTime.toString());
});Multiple schedules
One job file can export an array of cron expressions:
// crons/cleanup.ts
import { defineScheduled } from 'void';
export const cron = ['0 * * * *', '30 * * * *'];
export default defineScheduled(async (controller, env) => {
// Runs at :00 and :30 every hour
});defineScheduled
Wrap a handler in defineScheduled() to type its event, environment and execution context.
Jobs sharing a cron expression each run once per invocation. The SDK waits for all matching jobs and reports any failures. Files and directories starting with _ are ignored.
Local development
Schedules do not fire in local development. This step triggers a job through the SDK's dev endpoint.
POST /__void/scheduled
Content-Type: application/json
{ "cron": "<expression>", "scheduledTime": <unix_ms> }Set cron to an expression exported by your job. A successful call returns { "ok": true }.
The endpoint needs a local dev trigger token. At startup, the dev server prints a ready-to-paste curl command with it.
curl -X POST http://localhost:5173/__void/scheduled \
-H "Content-Type: application/json" \
-H "x-void-dev-trigger: <printed-token>" \
-d '{"cron":"0 * * * *","scheduledTime":'"$(date +%s000)"'}'Example output: The local cron handler runs, and its logs appear in the dev server.
The endpoint works in native SDK apps and supported frameworks. Framework jobs run in the adapter's development runtime and use the bindings it provides.
Deployment behavior
Native scheduled events need no manual token. For framework deploys, requests to /__void/scheduled need a matching x-void-internal token. The managed platform supplies its proxy token. For manual calls, set CRON_SECRET. An absent or mismatched token returns 401 without running a job.
On an SDK platform, each project can use up to 100 different cron expressions and 1,000 schedules (each expression a job exports counts as one schedule). Jobs that share an expression count once toward the expression limit. When you deploy to your own Cloudflare account, Cloudflare's Cron Trigger limits apply instead.