Β· By DevToolHub Team

Cron Expression Syntax Explained: A Visual Guide with Examples

A cron expression is a five-field string that defines a repeating schedule β€” when a task should run, down to the minute. The five fields represent minute, hour, day of month, month, and day of week. For example, 0 9 * * 1-5 means β€œat 9:00 AM, Monday through Friday.”

Every developer encounters cron expressions sooner or later β€” in a Linux crontab, a Kubernetes CronJob manifest, a GitHub Actions workflow, or an AWS EventBridge rule. Understanding the syntax will save you hours of trial and error and prevent costly mistakes like a job that fires every minute instead of every hour.

This guide explains each field, every special character, and shows real-world scheduling examples for backups, monitoring, reports, and maintenance. For a quick printable reference, see our Cron Expression Cheat Sheet.

The Five Fields

A standard cron expression consists of five fields separated by spaces:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ minute (0–59)
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ hour (0–23)
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ day of month (1–31)
β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ month (1–12 or JAN–DEC)
β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ day of week (0–6, Sun=0, or SUN–SAT)
β”‚ β”‚ β”‚ β”‚ β”‚
* * * * *

Each field accepts a number, a range, a list, a step value, or the wildcard *.

Special Characters

CharacterMeaningExampleDescription
*Any value* * * * *Every minute
,List1,15 * * * *At minute 1 and 15
-Range0 9-17 * * *Every hour from 9 to 17
/Step*/5 * * * *Every 5 minutes
?No specific value0 0 ? * MON(Quartz/Spring only)
LLast0 0 L * *Last day of month (Quartz only)
#Nth weekday0 0 ? * 5#33rd Friday of month (Quartz only)

The last three characters (?, L, #) are extensions found in Quartz Scheduler and Spring, not in standard Unix cron.

Common Examples

Here are the most frequently used cron schedules:

ExpressionSchedule
* * * * *Every minute
0 * * * *Every hour (at minute 0)
0 0 * * *Every day at midnight
0 9 * * 1-5Weekdays at 9:00 AM
0 0 1 * *First day of every month at midnight
*/5 * * * *Every 5 minutes
0 */2 * * *Every 2 hours
0 9,18 * * *At 9:00 AM and 6:00 PM daily
30 2 * * 0Every Sunday at 2:30 AM
0 0 1,15 * *1st and 15th of every month at midnight
0 6 * * 1Every Monday at 6:00 AM

Real-World Scheduling Examples

Database Backups

# Full backup every night at 3:00 AM
0 3 * * * /usr/local/bin/backup-db.sh full

# Incremental backup every 6 hours
0 */6 * * * /usr/local/bin/backup-db.sh incremental

# Weekly full backup on Sunday at 2:00 AM
0 2 * * 0 /usr/local/bin/backup-db.sh weekly

Log Rotation and Cleanup

# Delete logs older than 30 days, every day at 4:00 AM
0 4 * * * find /var/log/app -name "*.log" -mtime +30 -delete

# Compress yesterday's logs at 1:00 AM
0 1 * * * gzip /var/log/app/$(date -d yesterday +\%Y-\%m-\%d).log

Reports and Notifications

# Send weekly report every Monday at 9:00 AM
0 9 * * 1 /usr/local/bin/send-weekly-report.sh

# Health check every 5 minutes
*/5 * * * * curl -s https://example.com/health | grep -q "ok"

# Monthly billing report on the 1st at 8:00 AM
0 8 1 * * /usr/local/bin/generate-billing-report.sh

Cache and Queue Maintenance

# Clear expired cache every hour
0 * * * * redis-cli FLUSHDB

# Process stuck queue jobs every 15 minutes
*/15 * * * * /usr/local/bin/retry-failed-jobs.sh

Cron in Different Systems

The 5-field syntax is universal, but each platform has its own quirks.

Linux/macOS crontab

The original. Edit with crontab -e. Supports environment variables and special strings:

@reboot   /usr/local/bin/start-service.sh    # Run once at boot
@hourly   /usr/local/bin/sync.sh             # Same as "0 * * * *"
@daily    /usr/local/bin/cleanup.sh           # Same as "0 0 * * *"
@weekly   /usr/local/bin/report.sh            # Same as "0 0 * * 0"
@monthly  /usr/local/bin/archive.sh           # Same as "0 0 1 * *"

Reference: man 5 crontab

Kubernetes CronJobs

Standard 5-field syntax. All times are UTC unless the cluster is configured otherwise.

apiVersion: batch/v1
kind: CronJob
metadata:
  name: db-backup
spec:
  schedule: "0 3 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: backup-tool:latest
          restartPolicy: OnFailure

Kubernetes docs: CronJob

GitHub Actions

Uses 5-field cron in the schedule trigger. Times are always UTC.

on:
  schedule:
    - cron: '0 9 * * 1-5'  # Weekdays at 9:00 UTC

Minimum interval is 5 minutes. GitHub may delay execution by several minutes during peak load. See GitHub Actions: events that trigger workflows.

AWS EventBridge (CloudWatch Events)

Uses a 6-field format with a year field and ? for β€œno specific value”:

cron(0 9 ? * MON-FRI *)

The ? is required in either the day-of-month or day-of-week field. Reference: AWS Schedule Expressions.

Spring Framework (@Scheduled)

Uses a 6-field Quartz-compatible format with seconds:

@Scheduled(cron = "0 0 9 * * MON-FRI")  // Seconds first!
public void weekdayTask() { ... }

Note: the first field is seconds, not minutes. See Spring @Scheduled.

Celery (Python)

Uses crontab() objects that map to the 5-field standard:

from celery.schedules import crontab

app.conf.beat_schedule = {
    'daily-cleanup': {
        'task': 'tasks.cleanup',
        'schedule': crontab(hour=4, minute=0),  # 0 4 * * *
    },
}

Tips and Pitfalls

Day of week numbering varies. Standard cron uses 0 = Sunday, but some systems (ISO 8601, Quartz) use 1 = Monday. Always check your platform’s documentation.

Month and day-of-week can conflict. If you set both day-of-month and day-of-week to specific values, behavior varies by implementation. In standard cron, the job runs when either condition is met (OR logic), which is usually not what you want.

No seconds field in standard cron. If you need second-level precision, you’re likely using Quartz, Spring, or a similar extended format that adds a 6th field.

Timezone matters. Linux crontab uses the system timezone. Kubernetes and GitHub Actions use UTC. AWS lets you specify a timezone. Always document which timezone your cron job assumes.

Test before deploying. A wrong cron expression can fire thousands of times or never fire at all. Use a parser to verify your expression before putting it in production.

Try It Yourself

Use our Cron Expression Parser & Generator to test any expression and see the next 10 scheduled run times instantly. The Builder mode lets you construct expressions visually without memorizing the syntax.

For a compact, printable reference, grab the Cron Expression Cheat Sheet β€” it covers all five fields, special characters, platform differences, and common schedules on a single page.

You might also find the Unix Timestamp Converter useful when debugging time-related issues β€” and our article on Unix timestamps explains the format in depth. The Regex Cheat Sheet is handy if you’re combining cron with pattern-based log processing.

Further Reading

FAQ

What does */5 mean in a cron expression?
The / character means "every Nth." So */5 in the minute field means "every 5 minutes" β€” at 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55. You can also use it with a starting value: 3/5 means "every 5 minutes starting at minute 3" β€” 3, 8, 13, 18, etc.
What's the difference between 0 0 * * 0 and 0 0 * * 7?
Both mean "Sunday at midnight." In most cron implementations, both 0 and 7 represent Sunday. However, some systems (like AWS) only accept 0–6. Stick with 0 for maximum compatibility, or use the name SUN where supported.
Can I schedule a job to run every 30 seconds?
Standard cron doesn't support seconds β€” the minimum granularity is 1 minute. For sub-minute scheduling, run the job every minute and add a sleep inside the script: sleep 30 && /your/command. Alternatively, use Quartz, Spring, or a dedicated task queue like Celery.
How do I set a cron job for the last day of every month?
Standard cron doesn't have a "last day" keyword. A common workaround is to check the date in the script itself. Quartz supports this natively with L β€” 0 0 L * ? runs on the last day of every month.
Why does my GitHub Actions cron not trigger at the exact time?
GitHub Actions cron is best-effort. During peak load, scheduled workflows may be delayed by 5–15 minutes or even skipped. Don't use it for time-critical tasks. For precise scheduling, use a dedicated scheduler (crontab on a server, AWS EventBridge, etc.).
cron linux scheduling devops automation

Related Tools

Related Articles