DevGizmo
Back to Blog
generators·

How to Write CRON Expressions: A Complete Guide with Examples

CRON expressions define schedules for automated tasks. Learn the five-field syntax, special characters, common patterns, and how to avoid common pitfalls when writing CRON schedules for cron jobs, CI/CD pipelines, and cloud schedulers.

cronschedulinglinuxdevops

What Is a CRON Expression?

A CRON expression is a string of five (or six) fields that defines a recurring schedule. The cron daemon, originally created for Unix, reads these expressions to determine when to run scheduled commands.

CRON expressions are now used beyond Unix cron jobs — in GitHub Actions, AWS EventBridge, Kubernetes CronJobs, and virtually every cloud scheduler.

The Five-Field Syntax

┌───────────── 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

CharacterMeaningExample
*Any value* * * * * — every minute
,Value list0,30 * * * * — at 0 and 30 minutes past the hour
-Range0 9-17 * * * — every hour from 9am to 5pm
/Step*/15 * * * * — every 15 minutes
?No specific value (day fields only)0 12 ? * MON — noon every Monday
LLast (some implementations)0 0 L * * — last day of month at midnight
#nth occurrence (some implementations)0 10 * * 1#2 — second Monday of the month

Note: ? and L are not part of the POSIX standard but are supported by Quartz Scheduler (Java), AWS EventBridge, and GitHub Actions.

Common Patterns

# Every minute
* * * * *

# Every hour at minute 0
0 * * * *

# Every day at midnight
0 0 * * *

# Every day at 3:30am
30 3 * * *

# Every Monday at 9am
0 9 * * 1

# Every weekday at 9am (Monday–Friday)
0 9 * * 1-5

# Every 15 minutes
*/15 * * * *

# Every 6 hours
0 */6 * * *

# First day of every month at midnight
0 0 1 * *

# At midnight on the last day of the year (31 December)
0 0 31 12 *

# Every quarter (1st of Jan, Apr, Jul, Oct at midnight)
0 0 1 1,4,7,10 *

Day of Week Gotcha

Sunday is represented as both 0 and 7 in most implementations (POSIX uses 0–6, but 7 is also accepted for compatibility). However, 1 is Monday, which catches out developers used to the Date.getDay() JavaScript convention where 0 = Sunday and 1 = Monday — these happen to agree.

Six-Field and Seven-Field Variants

Some schedulers add fields:

  • Seconds field (prepended) — used by Quartz Scheduler, Spring @Scheduled, and some cloud services
    0 30 3 * * *    ← second, minute, hour, day, month, weekday
    
  • Year field (appended) — rare, used in some enterprise schedulers

Always check which format your target platform expects.

GitHub Actions Schedule Syntax

GitHub Actions uses standard 5-field CRON with UTC timezone:

on:
  schedule:
    - cron: "0 3 * * 1" # 3am UTC every Monday

Gotcha: GitHub Actions does not guarantee exact execution at the scheduled time during high-load periods. Schedules may be delayed by several minutes.

AWS EventBridge Rate and Cron Expressions

AWS EventBridge supports both rate expressions and cron expressions. The cron format uses 6 fields (with ? required for day-of-month or day-of-week when specifying the other):

cron(0 12 * * ? *)       # Every day at noon UTC
cron(0 9 ? * MON-FRI *)  # Every weekday at 9am UTC

Note that AWS cron fields follow a slightly different order (minute hour day-of-month month day-of-week year) and require the ? wildcard in either the day-of-month or day-of-week field.

Timezone Considerations

Standard Unix CRON runs in the server's local timezone. This can cause problems when servers are in UTC but your schedule should follow a local business timezone (e.g., "9am London time" which shifts with BST).

Most modern schedulers allow specifying a timezone explicitly. For example, Kubernetes CronJob:

spec:
  timeZone: "Europe/London"
  schedule: "0 9 * * 1-5"

Always specify a timezone explicitly rather than relying on the server default.

Debugging Tips

  • Use an online CRON visualiser (like DevGizmo's CRON Builder) to confirm your expression fires when expected
  • Check the next 5–10 trigger times before deploying
  • For */N step patterns, note that steps count from the minimum of the field, not from the first execution

Try it yourself

Put these concepts into practice with the free online tool on DevGizmo.