Run a job every hour
The cron expression for every hour is 0 * * * *. The 0 in the minute field fires at minute zero of every hour, 24 times a day. Leaving the minute as * would run it every minute instead.
crontab syntax · 5 fields
0****Next 5 runs
Vercel always runs schedules in UTC, and GitHub Actions does unless you set a time zone. Crontab and Kubernetes use the server's time zone.
Field by field
0Minute- At minute 0
*Hour- Every hour, 0 to 23
*Day of month- Every day of the month
*Month- Every month
*Day of week- Every day of the week
By platform
Most schedulers take the same five fields. The wrapper, time zone and limits differ.
crontab -e
# m h dom mon dow command
0 * * * * /usr/local/bin/sync.sh >> /var/log/sync.log 2>&1Runs in the server's local time zone
Cron starts jobs with a minimal environment: use absolute paths, and send output to a log so failures don't disappear.
.github/workflows/sync.yml
on:
schedule:
- cron: "0 * * * *"Runs in UTC unless you set a time zone
Add
timezone next to cron to use local time. Runs often start late when GitHub is busy, most of all at the start of an hour. In a public repository, GitHub turns the schedule off after 60 days without activity.cronjob.yaml (excerpt)
spec:
schedule: "0 * * * *"
timeZone: "Etc/UTC"
concurrencyPolicy: ForbidWithout timeZone, the controller's zone applies
Set timeZone to pin the schedule. concurrencyPolicy: Forbid stops a slow run from overlapping the next one.
AWS CLI
aws events put-rule \
--name sync-every-hour \
--schedule-expression "cron(0 * * * ? *)"Six fields, and one day field must be ?
EventBridge adds a year at the end and needs
? in day-of-month or day-of-week. For a plain interval, rate(1 hour) is simpler, though its runs are timed from when you create the rule rather than by the clock.vercel.json
{
"crons": [
{ "path": "/api/sync", "schedule": "0 * * * *" }
]
}Needs a paid plan
On Hobby, cron jobs run at most once a day, so this schedule fails at deploy time. Vercel runs crons in UTC.
Other hourly schedules
Change the minute to move the run off the top of the hour, or narrow the hour and weekday fields.
| Expression | Runs |
|---|---|
30 * * * * | Every hour at :30 |
0 9-17 * * * | Every hour from 09:00 through 17:00 |
0 * * * 1-5 | Every hour, on the hour, Monday through Friday |
@hourly | Same as 0 * * * * in crontab and Kubernetes CronJobs; other schedulers need the five fields |