Skip to content
Docs

Schedules Configuration Reference

Static schedules live in the schedules property of vercel.json. Edgenivo applies them when you deploy. To create schedules at runtime instead, use the SDK or the CLI.

schedules is an object. Each key is a schedule name, and each value defines when the schedule runs and what it targets:

vercel.json
{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "functions": {
    "api/cleanup.ts": {
      "experimentalTriggers": [{ "type": "schedule/v1beta" }]
    }
  },
  "schedules": {
    "cleanup": {
      "schedule": "0 * * * *",
      "timezone": "America/New_York",
      "jitter": 5,
      "function": "api/cleanup"
    },
    "daily-report": {
      "schedule": "0 9 * * *",
      "path": "/api/daily-report",
      "requestMethod": "GET"
    },
    "nightly-export": {
      "schedule": "0 2 * * *",
      "topic": "exports"
    }
  }
}
PropertyTypeRequiredDescription
schedulestringYesFive-field cron expression, evaluated in timezone
timezonestringNoIANA timezone, such as America/New_York. Defaults to UTC.
jitterintegerNoJitter window in minutes, from 1 to 15. Defaults to 1 on Pro and Enterprise. Hobby always uses 15.
functionstringOne targetFunction identifier of a private function with a schedule/v1beta trigger
servicestringNoName of the service that owns function. Only valid with function. See Target a function in a service.
pathstringOne targetPath on your deployment to send an HTTP request to. Must start with /. Up to 512 characters.
requestMethod"GET" or "POST"NoHTTP method for path. Defaults to POST. Only valid with path.
topicstringOne targetEdgenivo Queues topic to publish to. Letters, digits, _, and - only.

Set exactly one target: function, path, or topic. Static schedules don't accept a payload or a namespace. They always use the default namespace.

To learn how to write the code for each target, see Handling scheduled runs.

The key of each entry is the schedule's name. Names identify a schedule across deployments, so keep them stable. Renaming a schedule deletes the old schedule and creates a new one, with its own state and execution history.

Names and namespaces follow the same rules:

  • 1 to 256 characters
  • Start with an ASCII letter or digit
  • Contain only ASCII letters, digits, ., _, and -

Static schedule names must be unique within the project. Dynamic schedule names must be unique within their namespace. On Hobby, a deployment can declare up to 100 static schedules. See Limits.

Static schedules share the default namespace with dynamic schedules in the same environment, so the two can collide:

  • If you create a dynamic schedule with the name of an existing static schedule in default, the request fails with schedule_already_exists.
  • If a deployment declares a static schedule whose name a dynamic schedule in default already uses, Edgenivo skips that static schedule. The deployment still succeeds, and the dynamic schedule keeps its expression, target, payload, and state. The deployment's other static schedules apply as usual.

To use the static schedule, rename it or delete the dynamic schedule. Edgenivo creates the static schedule the next time a deployment that declares it becomes the current deployment of the environment or branch. To avoid collisions, create dynamic schedules in a namespace other than default.

The function property takes the function's path in the build output, not its source filename. The identifier is the path relative to .vercel/output/functions, without the .func suffix.

To find it:

  1. Run vercel build.
  2. Look in .vercel/output/functions for the function's .func directory.
  3. Use its relative path without .func. Keep any nested directories.

For example:

Source fileBuild outputfunction value
api/cleanup.ts.vercel/output/functions/api/cleanup.funcapi/cleanup
api/jobs/report.ts.vercel/output/functions/api/jobs/report.funcapi/jobs/report

The function must declare a schedule/v1beta trigger, and that must be its only trigger:

vercel.json
{
  "functions": {
    "api/cleanup.ts": {
      "experimentalTriggers": [{ "type": "schedule/v1beta" }]
    }
  }
}

The trigger makes the function private. It has no public URL, and only Edgenivo's scheduler can invoke it. Don't add routes or rewrites that point to it.

If no function in the build output matches function, or the function doesn't have the schedule/v1beta trigger, the deployment fails.

A service has its own build output. To target a function in a service, set service to the service name and function to the function's path within that service's output:

  1. Run vercel build.
  2. Look in .vercel/output/services/<service-name>/functions.
  3. Use the function's relative path without .func.

The following schedule targets .vercel/output/services/worker/functions/index.func:

vercel.json
{
  "schedules": {
    "cleanup": {
      "schedule": "0 * * * *",
      "service": "worker",
      "function": "index"
    }
  }
}

vercel dev doesn't run schedules that target a function in a service yet. It fails with DEV_SCHEDULE_SERVICE_FUNCTION_UNSUPPORTED. Deploy to test these schedules.

Schedules use the same five-field cron syntax as Cron Jobs:

FieldValuesExampleMeaning
Minute0 to 595 * * * *5 minutes past every hour
Hour0 to 230 5 * * *Every day at 05:00
Day of month1 to 310 0 5 * *Midnight on the 5th of each month
Month1 to 120 0 1 5 *Midnight on May 1
Day of week0 to 6 (Sunday to Saturday)0 9 * * 1-509:00 on weekdays

Expressions can use digits, *, ,, -, and /, with a single space between fields. They can't use:

  • Named days or months, such as MON or JAN
  • Both a day of the month and a day of the week in the same expression

The shortest interval between runs must be at least as long as the jitter window. On Hobby, that means a cron schedule can run at most once every 15 minutes. See Limits.

One-time schedules are only available as dynamic schedules. Pass a local date and time in YYYY-MM-DDTHH:mm format, such as 2026-10-01T09:00, to the SDK's at field or the CLI's --at option. Edgenivo evaluates it in the schedule's timezone.

  • You can add :00 seconds. Edgenivo stores the value with :00 either way.
  • Don't include Z, a UTC offset, fractional seconds, or non-zero seconds.

Frameworks can declare static schedules in their Build Output API output. Add a schedules object to .vercel/output/config.json with the same properties as vercel.json:

.vercel/output/config.json
{
  "version": 3,
  "schedules": {
    "cleanup": {
      "schedule": "0 3 * * *",
      "function": "_vercel/schedule"
    }
  }
}

Declare the trigger in the target function's .vc-config.json:

.vercel/output/functions/_vercel/schedule.func/.vc-config.json
{
  "runtime": "nodejs22.x",
  "handler": "index.mjs",
  "launcherType": "Nodejs",
  "experimentalTriggers": [{ "type": "schedule/v1beta" }]
}

vercel build combines a framework's schedules with the schedules in vercel.json. If the same name appears in both, the build fails with SCHEDULE_NAME_CONFLICT.


Was this helpful?

supported.