Cron syntax
A standard cron expression has five fields, separated by spaces:
| Field | Allowed values | Special characters |
|---|---|---|
| Minute | 0–59 | * , - / |
| Hour | 0–23 | * , - / |
| Day of month | 1–31 | * , - / |
| Month | 1–12 or JAN–DEC | * , - / |
| Day of week | 0–6 (0 and 7 are Sunday) or SUN–SAT | * , - / |
* means every value, , lists values, - is a range and / a step. Shortcuts like @daily, @hourly, @weekly and @monthly work too.
Common cron expressions
| Expression | Runs |
|---|---|
* * * * * | Every minute |
*/5 * * * * | Every 5 minutes |
*/15 * * * * | Every 15 minutes |
0 * * * * | Every hour, on the hour |
0 */6 * * * | Every 6 hours |
0 0 * * * | Every day at midnight |
30 9 * * * | Every day at 09:30 |
0 9 * * 1-5 | Weekdays at 09:00 |
0 0 * * 0 | Every Sunday at midnight |
0 0 1 * * | First day of every month |
0 0 1 1 * | Once a year, on 1 January |
0 9-17 * * 1-5 | Every hour from 09:00 to 17:00 on weekdays |
Cron in GitHub Actions, Kubernetes and Vercel
- GitHub Actions (
on: schedule: - cron:) runs in UTC, and the shortest interval is every 5 minutes. Runs can be delayed at busy times. - Kubernetes CronJobs use the same 5 fields; set
spec.timeZone(e.g.Africa/Lagos) to avoid UTC surprises. - Vercel Cron (in vercel.json) runs in UTC and calls one of your routes on schedule.
- Quartz, Spring and node-cron use 6 or 7 fields (seconds first, optional year) and characters like
?,Land#. This explainer covers standard 5-field cron.
The day-of-month and day-of-week gotcha
If both day fields are restricted, standard cron runs when either matches. 0 0 1 * 1 runs on the 1st of every month and every Monday, not only on Mondays that fall on the 1st. The explainer shows exactly which days match.
Scheduling jobs that call APIs? Check an API's uptime and status before relying on it, and convert timestamps with the Unix timestamp converter.