Complete Guide to Cron Expressions: Schedule Tasks Reliably
Cron is the standard scheduling syntax for Unix, Linux, cloud platforms, and application job runners. The free Cron Expression Generator builds and validates cron expressions with a visual interface — no signup, runs in your browser.
What Is Cron?
Cron is a time-based job scheduler built into Unix and Unix-like operating systems. It was created at Bell Labs in the early 1970s as part of the original Unix system and has been a standard tool on every Unix/Linux system since. The name comes from the Greek word for time, chronos.
The cron daemon (crond) runs continuously in the background, waking up every minute and checking a cron table (crontab) to see if any scheduled commands should run. If a command's schedule matches the current minute, cron executes it.
Cron has evolved well beyond Unix. Today, cron expression syntax is used in:
- AWS EventBridge, Google Cloud Scheduler, Azure Logic Apps
- Kubernetes CronJobs
- CI/CD platforms: GitHub Actions, GitLab CI, CircleCI
- Application frameworks: Node.js (node-cron), Python (APScheduler), Java (Quartz)
- Database schedulers: PostgreSQL pg_cron, MySQL Event Scheduler
The Five-Field Cron Syntax
A standard Unix cron expression has exactly five fields separated by spaces:
┌─────────── minute (0-59)
│ ┌───────── hour (0-23)
│ │ ┌─────── day of month (1-31)
│ │ │ ┌───── month (1-12)
│ │ │ │ ┌─── day of week (0-7, 0 and 7 = Sunday)
│ │ │ │ │
* * * * *| Field | Range | Special values |
|---|---|---|
| Minute | 0–59 | * = every minute |
| Hour | 0–23 | 0 = midnight, 12 = noon |
| Day of month | 1–31 | * = every day, L = last day (some platforms) |
| Month | 1–12 or JAN–DEC | * = every month |
| Day of week | 0–7 (0 and 7 = Sunday) or SUN–SAT | * = every day, ? = don't care (Quartz only) |
Special Characters
* — Wildcard (any value)
Matches every value in the field. * * * * * runs every minute of every hour of every day — 1,440 times per day. In production this is almost always a mistake.
/ — Step values
*/N means “every N units.” */15 in the minute field runs at :00, :15, :30, :45 of every hour. */2 in the hour field runs at midnight, 2am, 4am, etc.
*/15 * * * * # Every 15 minutes
0 */6 * * * # Every 6 hours (midnight, 6am, noon, 6pm)
0 0 */3 * * # Every 3 days at midnight- — Range
9-17 in the hour field means hours 9 through 17 inclusive. Used for “business hours” style schedules.
0 9-17 * * 1-5 # At the top of every business hour (9am-5pm, Mon-Fri)
* 9-17 * * 1-5 # Every minute during business hours (careful!), — List
Specifies multiple specific values. 0,30 means at :00 and :30.
0 8,12,17 * * * # At 8am, noon, and 5pm daily
0 0 * * 1,3,5 # Midnight on Monday, Wednesday, Friday? — Don't care (Quartz / AWS)
Used in day-of-month or day-of-week to mean “I don't care about this field.” Required when you specify the other day field to avoid ambiguity. Standard Unix cron does not support ? — it is specific to Quartz Scheduler, AWS EventBridge, and some other platforms.
Common Cron Patterns
| Expression | Meaning | Use case |
|---|---|---|
0 0 * * * | Daily at midnight | Database backups, log rotation |
0 9 * * 1-5 | 9am weekdays | Daily standups, morning reports |
*/15 * * * * | Every 15 minutes | Health checks, queue processors |
0 0 * * 0 | Weekly on Sunday midnight | Weekly cleanup, archive jobs |
0 2 * * * | Daily at 2am | Backup jobs (low traffic window) |
0 0 1 * * | First of each month | Monthly billing, reporting |
30 14 * * * | Daily at 2:30pm | Afternoon notifications |
0 0 1 1 * | January 1st at midnight | Annual reset jobs |
5 4 * * 0 | Sunday at 4:05am | Off-peak maintenance |
Platform Differences
AWS EventBridge (formerly CloudWatch Events)
AWS extends cron with a 6th field for year and uses a cron() wrapper:
# AWS format: cron(minute hour day-of-month month day-of-week year)
cron(0 14 * * ? *) # Daily at 2pm UTC
cron(0 9 ? * MON-FRI *) # Weekdays at 9am UTCNote: AWS requires ? in either day-of-month or day-of-week. AWS cron runs in UTC only — there is no timezone support at the expression level.
GitHub Actions
on:
schedule:
- cron: '0 9 * * 1-5' # Weekdays at 9am UTC
jobs:
daily-task:
runs-on: ubuntu-latestGitHub Actions cron uses standard 5-field syntax in UTC. Minimum interval is every 5 minutes (GitHub may delay free-tier jobs by up to 15 minutes under load).
Kubernetes CronJobs
apiVersion: batch/v1
kind: CronJob
metadata:
name: daily-backup
spec:
schedule: "0 2 * * *" # Standard 5-field, cluster timezone
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: backup-tool:latestKubernetes uses standard 5-field syntax. From Kubernetes 1.25, you can specify a timezone: timeZone: "America/New_York".
Quartz Scheduler (Java)
Quartz uses a 6-field (or 7-field with year) format with seconds as the first field:
# Quartz: seconds minutes hours day-of-month month day-of-week [year]
0 0 9 ? * MON-FRI # 9am on weekdays
0 */30 * ? * * # Every 30 minutesTimezone Handling
This is the most common source of cron surprises. Key rules:
- Unix cron — runs in the system timezone.
TZ=America/New_Yorkcan be set per-job in the crontab. - AWS EventBridge — UTC only. Convert your desired time to UTC before writing the expression.
- Google Cloud Scheduler — supports timezone selection in the UI or API. Default is UTC.
- Kubernetes 1.25+ —
timeZonefield accepts IANA timezone names. - GitHub Actions — UTC only.
Always document the timezone next to the cron expression in code comments. “9am daily” is meaningless without knowing which timezone. A cron job that runs at 9am UTC runs at 4am in New York, 10am in Paris, and 6pm in Tokyo simultaneously.
Best Practices
Stagger jobs to avoid thundering herds
If every job runs at 0 0 * * *, your database gets hit simultaneously at midnight. Spread jobs: 0 0 * * *, 5 0 * * *, 10 0 * * *. A few minutes apart avoids spikes with no functional difference.
Avoid every-minute in production
* * * * * is 1,440 executions per day. If your job takes more than a minute, runs start queuing up. Use a proper background job queue (Sidekiq, Celery, BullMQ) for sub-minute work or work that needs concurrency control.
Use the generator to verify next run times
Always test your cron expression in the Cron Expression Generator before deploying. It shows the next 10 execution times so you can confirm your expression actually matches what you intend. Off-by-one errors in day-of-week (0 vs 7 for Sunday, 1-indexed vs 0-indexed months) are common and silent failures.
Log start time and duration
Log when your job starts and how long it took. This lets you detect missed runs, overlapping runs (job takes longer than its interval), and gradual performance degradation. Many cron monitoring tools (Healthchecks.io, Cronitor, Better Uptime) can alert you if a cron job does not report in within an expected window.
Build Cron Expressions Free Online
Visual selector, shows next 10 run times, AWS and Quartz formats supported. No signup.
Open Cron Expression Generator