Tutorial2024-05-11

Cron Expressions Explained: A Backend Engineer's Guide to Scheduling

Cron expressions look simple but have enough edge cases to fill a book. Here's everything you need to know — from basics to production pitfalls.

#cron#scheduling#backend#linux#devops

Cron 表达式,看着简单,实际上坑比你想的多得多。

I've been writing backend services for 15 years. Cron expressions are one of those things everyone thinks they understand — until they miss a 3 AM job because of daylight saving time.

Let me give you the definitive guide.

The Format

┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-7, 0 and 7 are Sunday)
│ │ │ │ │
* * * * *

Common Patterns

# Every day at 3:00 AM
0 3 * * *

# Every Monday at 9:00 AM
0 9 * * 1

# Every 15 minutes
*/15 * * * *

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

# Every weekday at 8:30 AM
30 8 * * 1-5

# Every 2 hours during business hours
0 9-17/2 * * 1-5

The Edge Cases

1. Day of Month + Day of Week

# This runs on the 15th AND every Monday (UNION, not intersection)
0 0 15 * 1

Most people expect this to run on the 15th only if it's a Monday. Wrong. It runs on the 15th of every month AND every Monday.

2. February 30th

# Runs on Jan 30, Mar 30, Apr 30, etc. — never Feb 30
0 0 30 * *

3. Daylight Saving Time

# This might run at 2:00 AM standard time OR 3:00 AM daylight time
0 2 * * *

During DST transitions, 2 AM might not exist (spring forward) or might occur twice (fall back). Use UTC in production.

4. Leap Years

# February 29 only runs every 4 years
0 0 29 2 *

Production Best Practices

  1. Always use UTCTZ=UTC in your crontab
  2. Add jitter — Don't run everything at midnight. Add random minutes.
  3. Log everything — Cron failures are silent by default
  4. Use locking — Prevent overlapping runs with flock
  5. Test with cronexpr — Validate your expression before deploying

Cron in Modern Systems

Modern schedulers use cron-like syntax:

# Kubernetes CronJob
schedule: "0 3 * * *"

# GitHub Actions
on:
  schedule:
    - cron: '0 3 * * *'

# Cloudflare Workers
triggers:
  crons:
    - "0 3 * * *"

Quick Reference

Pattern Meaning
* * * * * Every minute
0 * * * * Every hour
0 0 * * * Every day at midnight
0 0 * * 0 Every Sunday at midnight
0 0 1 * * First of every month
*/5 * * * * Every 5 minutes

Need to figure out when your cron job will run next? Use our free Cron Expression Generator — visual timeline, human-readable output, and common pattern library.

🛠

Try It Yourself

Put what you've learned into practice with our free online tools.