UseToolSuite UseToolSuite

Cron Expression Guide: Syntax, Examples, and Common Patterns

Master cron syntax with clear examples. Learn standard 5-field and 6-field formats, special characters, DST anomalies, and platform differences for Linux, AWS, and Kubernetes.

Necmeddin Cunedioglu Necmeddin Cunedioglu 8 min read
Part of the Time & Date in Programming: The Complete Developer Guide series

Practice what you learn

Cron Expression Parser

Try it free →

Cron Expression Guide: Syntax, Examples, and Common Patterns

Since its creation in the 1970s for the Unix operating system, cron has remained the undisputed standard for scheduling recurring tasks. Despite its age, the cryptic strings of asterisks and numbers that make up a cron expression appear everywhere in modern infrastructure — from server maintenance shell scripts and database backups, to AWS Lambda triggers, GitHub Actions, and Kubernetes CronJobs.

Writing an incorrect cron expression doesn’t just result in a syntax error; it can cause serious financial damage. A misconfigured script meant to run “once a month” might accidentally run “every minute of every day for a month,” overwhelming your database and racking up thousands of dollars in cloud computing bills.

This comprehensive guide breaks down standard 5-field cron syntax, extends into 6-field and AWS variations, provides battle-tested examples, and highlights the dangerous edge cases (like Daylight Saving Time anomalies) that frequently cause production outages.

Stop guessing. Validate your schedules instantly with our Cron Expression Parser — it translates any cron expression into plain English and calculates the exact next 5 scheduled run times.

The Standard 5-Field Cron Format

Standard Linux cron (the version found in crontab on Ubuntu, Debian, macOS, etc.) uses 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, where Sunday = 0 or 7)
│ │ │ │ │
* * * * *

When the system clock matches the criteria defined in all five fields, the scheduled command executes.

Valid Field Values

Every field can contain one of the following structures:

StructureSyntaxMeaningExample
Exact NumbernMatch exactly this value5 in the minute field means “exactly at 5 minutes past the hour”
Asterisk (Any)*Match every possible value* in the hour field means “every hour”
Rangex-yMatch inclusive values between x and y9-17 in the hour field means “from 9 AM to 5 PM inclusive”
List (Comma)x,y,zMatch a specific set of values1,15 in the day field means “on the 1st and 15th of the month”
Step (Slash)*/nMatch every nth value*/15 in the minute field means “every 15 minutes”

Note: You can combine these! 0 8-17/2 * * 1-5 means “every 2 hours between 8 AM and 5 PM, Monday through Friday.”

Essential Cron Expression Examples

Here is a cheat sheet of the most frequently used cron expressions in production environments.

Minutes and Hours

ExpressionPlain English TranslationUse Case
* * * * *Every single minuteHealth checks, high-frequency polling
*/5 * * * *Every 5 minutesCache clearing, queue processing
0 * * * *Every hour, exactly at the top of the hour (:00)Hourly log rotation
30 * * * *Every hour, at 30 minutes past the hourStaggered hourly jobs
0 */6 * * *Every 6 hours (00:00, 06:00, 12:00, 18:00)Mid-day data synchronization

Daily and Weekly

ExpressionPlain English TranslationUse Case
0 0 * * *Every day at midnight exactlyDaily database backups
0 8 * * *Every day at 8:00 AMMorning report generation
30 18 * * 1-5Every weekday (Mon-Fri) at 6:30 PMShutting down staging servers
0 2 * * 0Every Sunday at 2:00 AMWeekly deep system scans

Monthly and Yearly

ExpressionPlain English TranslationUse Case
0 0 1 * *Midnight on the first day of every monthMonthly billing cycles
0 0 1,15 * *Midnight on the 1st and 15th of the monthBi-monthly payroll tasks
0 0 1 1 *Midnight on January 1st every yearYearly SSL certificate checks

Special Shorthand Strings (Macros)

To make crontab files more readable, standard Linux cron daemon implementations support special predefined string macros. Instead of writing five asterisks, you can write a single word starting with @.

MacroEquivalent ExpressionDescription
@yearly0 0 1 1 *Run once a year, on Jan 1 at midnight.
@annually0 0 1 1 *Identical to @yearly.
@monthly0 0 1 * *Run once a month, on the 1st at midnight.
@weekly0 0 * * 0Run once a week, on Sunday at midnight.
@daily0 0 * * *Run once a day, at midnight.
@hourly0 * * * *Run once an hour, at the beginning of the hour.
@reboot(None)Crucial: Run exactly once when the server boots up. Perfect for startup scripts.

Warning: While these are standard in Linux crond, they are NOT universally supported in cloud platforms like AWS CloudWatch or GitHub Actions. When in doubt, use the explicit 5-field syntax.

The 6-Field Format (Seconds)

Standard cron does not support a “seconds” field. The finest granularity in Linux cron is 1 minute. However, many modern software frameworks (like Java’s Spring Framework, Quartz Scheduler, or Go’s robfig/cron) extended the syntax to 6 fields to allow sub-minute precision.

┌─────────────── second (0–59)
│ ┌───────────── minute (0–59)
│ │ ┌───────────── hour (0–23)
│ │ │ ┌───────────── day of month (1–31)
│ │ │ │ ┌───────────── month (1–12)
│ │ │ │ │ ┌───────────── day of week (0–7)
│ │ │ │ │ │
* * * * * *

If you see a 6-field cron expression (e.g., 0/30 * * * * *), it means it is a framework-specific implementation running “every 30 seconds.”

Platform Syntax Differences

Not all cron engines are created equal. When moving from a bare-metal Linux server to a managed cloud service, syntax differences can break your schedules.

AWS CloudWatch Events / EventBridge

AWS uses a highly modified 6-field format (adding a ‘Year’ field at the end, not a ‘Seconds’ field at the beginning): cron(minute hour day-of-month month day-of-week year).

AWS imposes strict rules:

  • You cannot use * in both the day-of-month and day-of-week fields simultaneously. One of them must be a ? (question mark).
  • Supports advanced modifiers: L (Last day of month), W (Nearest weekday).
  • Example: cron(0 12 * * ? *) — Runs every day at noon UTC.

Kubernetes CronJobs

Kubernetes (K8s) uses the standard 5-field format in its manifest files.

  • Before K8s 1.27, all CronJobs strictly ran in UTC based on the kube-controller-manager clock.
  • In K8s 1.27+, you can explicitly declare timezones: spec.timeZone: "America/New_York".

GitHub Actions

GitHub uses the standard 5-field format inside workflow YAML files: on: schedule: - cron: '0 0 * * *'.

  • All jobs execute in UTC.
  • Limitation: The minimum supported interval is 5 minutes. GitHub explicitly states that they may delay scheduled jobs during times of high platform load. Do not rely on GitHub Actions for mission-critical, exact-minute timing.

Avoiding Catastrophic Cron Mistakes

1. The “Every 5 Minutes” Typo

This is the most common mistake made by beginners:

# ❌ FATAL ERROR: This does NOT mean "every 5 minutes." 
# It means "run exactly at the 5th minute of every hour" (1:05, 2:05, 3:05).
5 * * * *

# ✅ CORRECT: The slash indicates a step value (every 5th minute).
*/5 * * * *

2. The “Last Day of the Month” Problem

Standard Linux cron does not support the L character to find the last day of the month. Because months have 28, 29, 30, or 31 days, you cannot hardcode a number.

The Workaround: Run the job on days 28-31, but add bash logic to check if tomorrow is the 1st of the month before executing the real script.

0 23 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && /path/to/monthly-billing.sh

3. The Daylight Saving Time (DST) Anomaly

Cron relies entirely on the server’s system clock. If your server is configured to a local timezone that observes Daylight Saving Time (e.g., America/New_York), you are exposed to DST transition bugs.

  • Spring Forward: At 2:00 AM, the clock jumps to 3:00 AM. If you have a cron job scheduled at 30 2 * * * (2:30 AM), it will never run that day.
  • Fall Back: At 3:00 AM, the clock jumps back to 2:00 AM. If you have a cron job scheduled at 30 2 * * *, it will run twice that day.

The Fix: Always run your servers in UTC (sudo timedatectl set-timezone UTC). UTC does not observe Daylight Saving Time, meaning every minute of the year happens exactly once. If you must run jobs at local times, use an application-level scheduler (like Celery or Agenda) rather than system cron.

Debugging Failed Cron Jobs

A core philosophy of cron is that it fails silently. It has no terminal attached to it, so if a script throws an error, you won’t see it unless you explicitly capture the output.

1. Always Redirect Output

Never deploy a cron job without capturing stdout and stderr to a log file:

# Append both normal output (1) and error output (2) to the log file
0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup_job.log 2>&1

2. The Absolute Path Rule

When you log into a server, your .bashrc loads your $PATH. When cron runs, it runs in a highly restricted shell (usually /bin/sh) with a minimal $PATH.

A script that runs perfectly when you type ./backup.sh may fail in cron because cron cannot find the node, python, or aws executables.

The Fix: Always use absolute paths for both the script and the executables inside the script.

# ❌ BAD: cron might not find 'node'
0 * * * * node /var/www/script.js

# ✅ GOOD: Provide the absolute path to the executable
0 * * * * /usr/local/bin/node /var/www/script.js

Further Reading


Never deploy a cron expression without testing it first. Use our completely free Cron Expression Parser to translate your syntax into human-readable text and verify the exact upcoming execution times.

Necmeddin Cunedioglu
Necmeddin Cunedioglu Author
8 min read
-- views

Software developer and the creator of UseToolSuite. I write about the tools and techniques I use daily as a developer — practical guides based on real experience, not theory.