Cron Expression Guide — Syntax, Fields, and Special Characters
Cron expressions schedule recurring jobs using five or six fields: minute, hour, day-of-month, month, day-of-week. Here's the full cron syntax including *, /, -, and ?...
Cron expressions are strings of 5 or 6 fields that specify when a scheduled job should run. Used in Unix cron, GitHub Actions, AWS CloudWatch, Kubernetes CronJobs, and many schedulers.
Use the Cron Builder to build and validate cron expressions visually.
Standard 5-field cron format
┌───────────── 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, 0=Sunday)
│ │ │ │ │
* * * * *
Special characters
| Character | Meaning | Example |
|---|---|---|
* | Every value | * * * * * = every minute |
, | List of values | 1,15 * * * * = at minute 1 and 15 |
- | Range | 1-5 * * * * = minutes 1,2,3,4,5 |
/ | Step | */15 * * * * = every 15 minutes |
? | No specific value (day fields) | 0 12 * * ? |
L | Last (some schedulers) | 0 0 L * * = last day of month |
# | Nth occurrence (some schedulers) | 0 9 * * 2#1 = first Tuesday at 9am |
Common cron expressions
# Every minute:
* * * * *
# Every 5 minutes:
*/5 * * * *
# Every 15 minutes:
*/15 * * * *
# Every hour (at :00):
0 * * * *
# Every 2 hours:
0 */2 * * *
# Every day at midnight:
0 0 * * *
# Every day at 6am:
0 6 * * *
# Every day at 6am and 6pm:
0 6,18 * * *
# Every weekday (Mon–Fri) at 9am:
0 9 * * 1-5
# Every Monday at 9am:
0 9 * * 1
# Every Sunday at midnight:
0 0 * * 0
# 1st of every month at midnight:
0 0 1 * *
# Every 3 months (quarterly), 1st at midnight:
0 0 1 */3 *
# Every January 1st at midnight:
0 0 1 1 *
# Weekdays every 30 minutes, 9am–5pm:
*/30 9-17 * * 1-5
6-field format (with seconds)
Some schedulers (Quartz, Spring, AWS EventBridge) use a 6-field format:
┌─────────────── second (0–59)
│ ┌───────────── minute (0–59)
│ │ ┌───────────── hour (0–23)
│ │ │ ┌───────────── day of month (1–31)
│ │ │ │ ┌───────────── month (1–12)
│ │ │ │ │ ┌───────────── day of week (0–6)
│ │ │ │ │ │
0 * * * * * = every minute at :00 seconds
0 0 * * * * = every hour at 0:00
0 0 9 * * 1-5 = weekdays at 9:00:00
GitHub Actions schedule syntax
GitHub Actions uses standard 5-field cron in UTC:
on:
schedule:
# Every day at 2am UTC:
- cron: '0 2 * * *'
# Every Monday at 9am UTC:
- cron: '0 9 * * 1'
# Every 6 hours:
- cron: '0 */6 * * *'
# First and fifteenth of each month:
- cron: '0 0 1,15 * *'
jobs:
scheduled-task:
runs-on: ubuntu-latest
steps:
- run: echo "Running scheduled job"
Note: GitHub Actions schedules are always UTC. Minimum interval is 5 minutes; schedules may run late during high load.
Kubernetes CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: backup-job
spec:
schedule: "0 2 * * *" # 2am daily
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: backup-tool:latest
command: ["/backup.sh"]
restartPolicy: OnFailure
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
Node.js with node-cron
import cron from 'node-cron';
// Every 5 minutes:
cron.schedule('*/5 * * * *', () => {
console.log('Running every 5 minutes');
});
// Weekdays at 9am:
cron.schedule('0 9 * * 1-5', () => {
sendDailyReport();
}, {
timezone: 'America/New_York',
});
// With error handling:
cron.schedule('0 0 * * *', async () => {
try {
await cleanupOldFiles();
} catch (err) {
console.error('Daily cleanup failed:', err);
}
});
Python with APScheduler
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
scheduler = BackgroundScheduler()
# Every day at 2am:
scheduler.add_job(
backup_database,
CronTrigger(hour=2, minute=0),
id='daily_backup'
)
# Every weekday at 9am:
scheduler.add_job(
send_report,
CronTrigger(day_of_week='mon-fri', hour=9, minute=0),
id='weekday_report'
)
scheduler.start()
Cron gotchas
Day-of-month AND day-of-week are OR’d:
# This runs on the 1st of the month OR every Monday:
0 0 1 * 1
# To run ONLY on Monday the 1st:
# → Not directly expressible in standard cron (use application logic)
No second granularity in standard cron:
# To run every 30 seconds, you need two entries:
*/1 * * * * # every minute at :00
*/1 * * * * # can't do :30
# → Use a scheduler with second support, or sleep(30) inside the job
Timezones: Standard Unix cron runs in the server’s local timezone. Always specify timezone explicitly in application schedulers.
Related tools
- Cron Builder — build cron expressions visually
- Cron Schedule Examples — common cron patterns
- GitHub Actions Schedule — GitHub CI scheduling
Related posts
- Cron Expression Syntax, Explained by Field — Five fields, nine special characters, a dozen edge cases. A complete reference f…
- Cron Pitfalls: Timezones, DST, and Missed Runs — Your cron job will run twice or skip entirely when DST changes. Here's why, how …
- AWS EventBridge Scheduler — Cron Schedules for Lambda and AWS Services — AWS EventBridge Scheduler runs Lambda functions, ECS tasks, and other AWS target…
- Cron Schedule Examples — Common Cron Expressions for Any Interval — Cron expressions schedule recurring jobs. Here's a reference of common cron sche…
- GitHub Actions Scheduled Workflows — cron Syntax and Examples — Schedule GitHub Actions workflows with cron expressions using the schedule trigg…
Related tool
Build and parse cron expressions with human-readable explanations.
Written by Mian Ali Khalid. Part of the Dev Productivity pillar.