Cron Expression Examples

A practical, copy-paste reference for the cron expressions developers actually need: every 5 minutes, hourly, daily at midnight, weekdays at 9am, the first of every month, and dozens more. Every example includes the raw expression, a plain-English description, and the next few times it will fire.

Cron Syntax in 30 Seconds

A standard cron expression has five space-separated fields, each controlling a different unit of time:

┌───────────── 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 and 7 both = Sunday)
│ │ │ │ │
* * * * *   command to run

Within each field, you can use:

  • * — every value
  • 5 — a specific value
  • 1,3,5 — a list of values
  • 1-5 — a range (inclusive)
  • */15 — a step, meaning "every 15 starting at 0"
  • 0-30/5 — a range with a step

Combine these building blocks and you can express almost any recurring schedule.

Every Minute / Sub-Hourly Schedules

* * * * *           # Every minute
*/5 * * * *         # Every 5 minutes
*/10 * * * *        # Every 10 minutes
*/15 * * * *        # Every 15 minutes (quarter-hourly)
*/30 * * * *        # Every 30 minutes (half-hourly)
0,30 * * * *        # Also every 30 minutes — at :00 and :30
5,35 * * * *        # Every 30 minutes starting at :05 and :35

Gotcha: */7 * * * * does not evenly run every 7 minutes across the hour — it fires at :00, :07, :14, :21, :28, :35, :42, :49, :56, then skips to :00 the next hour, leaving a 4-minute gap. Only divisors of 60 (1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30) produce a truly uniform schedule with step syntax.

Hourly Schedules

0 * * * *           # Every hour on the hour
15 * * * *          # Every hour at :15
0 */2 * * *         # Every 2 hours (midnight, 2am, 4am, ...)
0 */4 * * *         # Every 4 hours
0 */6 * * *         # Every 6 hours (midnight, 6am, noon, 6pm)
0 9-17 * * *        # Every hour from 9am to 5pm inclusive
0 9,12,17 * * *     # At 9am, noon, and 5pm only

Daily Schedules

0 0 * * *           # Every day at midnight (00:00)
0 12 * * *          # Every day at noon
30 2 * * *          # Every day at 2:30am
0 6 * * *           # Every morning at 6am
45 23 * * *         # Every night at 11:45pm
@daily              # Shorthand for 0 0 * * * (also @midnight)

Prefer off-peak times like 2am or 3am for heavy daily jobs to avoid overlapping with peak traffic. And be careful around 2:00-3:00am local time during daylight-saving transitions — the hour may not exist, or may exist twice.

Weekly Schedules

0 0 * * 0           # Every Sunday at midnight
0 0 * * 1           # Every Monday at midnight
0 9 * * 1           # Every Monday at 9am
0 18 * * 5          # Every Friday at 6pm
0 9 * * 1-5         # Weekdays at 9am (Mon-Fri)
0 9 * * MON-FRI     # Same thing using names
0 10 * * 6,0        # Weekends at 10am (Saturday and Sunday)
@weekly             # Shorthand for 0 0 * * 0 (Sunday midnight)

Both 0 and 7 mean Sunday in the day-of-week field. Most modern cron implementations accept either.

Monthly and Yearly Schedules

0 0 1 * *           # First day of every month at midnight
0 9 1 * *           # First of every month at 9am
0 0 15 * *          # 15th of every month at midnight
0 0 28-31 * *       # Likely last day — runs 28, 29, 30, 31 when they exist
0 0 1 1 *           # Every January 1st at midnight (new year)
0 0 1 */3 *         # First of every 3rd month (quarterly)
0 0 1 1,4,7,10 *    # First of January, April, July, October
@monthly            # Shorthand for 0 0 1 * *
@yearly             # Shorthand for 0 0 1 1 * (also @annually)

Last day of month is surprisingly hard in standard cron. Most people use 0 0 28-31 * * combined with a date check inside the script ([ "$(date -d tomorrow +%d)" = "01" ] || exit 0). Some extended cron flavours — like Quartz, Jenkins, and AWS EventBridge — support an L character for "last."

Business-Hours Schedules

*/15 9-17 * * 1-5   # Every 15 min, 9am-5pm, weekdays
0 9-18 * * 1-5      # Every hour on the hour, 9am-6pm, weekdays
0 9 * * 1           # Mondays at 9am (weekly standup)
0 17 * * 5          # Fridays at 5pm (end-of-week summary)
30 8 * * 1-5        # 8:30am weekdays (morning prep job)

Shorthand Aliases

Most cron implementations (Vixie cron, cronie, Kubernetes CronJobs, GitHub Actions) accept the following shortcuts:

@reboot       # Once at system startup
@yearly       # Equivalent to 0 0 1 1 * (also @annually)
@monthly      # Equivalent to 0 0 1 * *
@weekly       # Equivalent to 0 0 * * 0
@daily        # Equivalent to 0 0 * * * (also @midnight)
@hourly       # Equivalent to 0 * * * *

These aliases are cleaner but opaque — stick to explicit expressions in production config where the schedule matters for on-call debugging.

Common Mistakes

The step trap. */5 starts at 0, so */5 * * * * runs at :00, :05, :10. If you wanted to start at :03, you need 3,8,13,18,... or 3-59/5, not */5 with an offset.

Day-of-month + day-of-week OR. Setting both fields to specific values uses OR logic, not AND. 0 0 1 * 1 runs on the 1st of every month AND on every Monday — not "the 1st if it's a Monday."

PATH surprises. Cron jobs run with a minimal PATH (typically just /usr/bin:/bin). If your script relies on tools installed elsewhere, set PATH at the top of the crontab or use absolute paths.

Output lost forever. By default, cron emails output to the user. If no mailer is configured, the output is discarded. Redirect stdout and stderr explicitly: 0 * * * * /path/script >> /var/log/myjob.log 2>&1.

DST double-runs. Jobs scheduled at 2:30am run twice on the day the clocks go back and zero times on the day they spring forward. Use UTC (CRON_TZ=UTC) for anything that matters.

Testing Your Expression

Before deploying, always preview the next run times. Our cron expression generator shows the next several occurrences and validates the syntax as you type — no more hoping that */15 9-17 * * 1-5 does what you think.

For quick manual checks on a Linux box, crontab -l lists current jobs and systemctl list-timers shows systemd timers with their scheduled run times. On Kubernetes, kubectl get cronjob shows LAST SCHEDULE and ACTIVE at a glance.

Build a Custom Schedule

Need something more specific than the examples above? Our cron expression generator lets you build an expression visually and see the next 5 run times instantly. Perfect for double-checking a tricky schedule before committing it to version control.

Frequently Asked Questions

How do I write a cron expression that runs every 5 minutes?

Use */5 * * * *. The */5 in the minute field means "at every 5th minute starting from 0" — so the job runs at :00, :05, :10, :15, and so on. Every other field is a wildcard, meaning any hour, any day of the month, any month, any day of the week.

What does the asterisk (*) mean in cron?

The asterisk means "every value in this field." In the minute field, * means every minute (0-59). In the hour field, * means every hour (0-23). A cron expression of * * * * * means every minute of every hour of every day — the most frequent schedule possible in standard cron.

Can cron run more than once per minute?

Standard Unix cron has a minimum granularity of one minute. If you need sub-minute scheduling, either use a different scheduler (systemd timers with OnUnitActiveSec=30s, or a task queue like Celery Beat), or run a job every minute that internally sleeps and repeats — for example, a shell loop that executes a task every 30 seconds.

What is the difference between cron day-of-month and day-of-week?

Day-of-month (field 3, values 1-31) picks specific calendar days. Day-of-week (field 5, values 0-6 or SUN-SAT) picks specific weekdays. When both fields are set to something other than *, cron runs the job on days that match either field — this is a common source of bugs. If you want "only on the 1st and only if it is a Monday," standard cron cannot express that directly and you need to check inside your script.

What time zone does cron use?

Traditional cron uses the system's local time zone, which can cause double runs or missed runs during daylight saving transitions. Modern implementations let you set a CRON_TZ=UTC line at the top of the crontab to pin a specific zone — strongly recommended if your server spans regions. Kubernetes CronJobs default to UTC unless you set spec.timeZone.