The Shack Developer Tips Cron Expressions Explained

Cron Expressions Explained: Scheduling Jobs Without the Headache

Back to All Posts

Every developer eventually needs to schedule something — a nightly database backup, an hourly report, a weekly cleanup job. Cron is how Unix-like systems (and countless cloud services) handle scheduled tasks, and the expression syntax has become a near-universal standard. Once you understand the five fields, the rest follows logically.

The DevToolShack Cron Expression Builder lets you build expressions visually and see a plain-English description of what the schedule means — no more guessing whether 0 9 * * 1 is 9am every Monday or every minute of the 9th hour.

The Five-Field Structure

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

Each field accepts a specific value, a wildcard, a range, a step, or a list. The fields are always in this order — minute first, day-of-week last.

Special Characters

CharacterMeaningExample
*Any / every value* in hour = every hour
,List of values1,15 = 1st and 15th
-Range9-17 = hours 9 through 17
/Step*/15 = every 15 units

Reading Common Expressions

ExpressionMeaning
* * * * *Every minute
0 * * * *Every hour (at :00)
0 9 * * *Every day at 9:00 AM
0 9 * * 1Every Monday at 9:00 AM
0 9 * * 1-5Weekdays at 9:00 AM
0 0 1 * *First day of every month at midnight
0 0 1 1 *January 1st at midnight (yearly)
*/15 * * * *Every 15 minutes
0 9,17 * * *Daily at 9:00 AM and 5:00 PM
0 0 * * 0Every Sunday at midnight

The Gotchas

Timezone is the server's timezone

Cron runs in the timezone of the system it's on — which may not be your timezone, and almost certainly isn't your users' timezone. Always check what timezone your server or cloud scheduler uses. Many cloud services (AWS EventBridge, GitHub Actions) let you specify a timezone explicitly; use this whenever you need "9am in London" rather than "9am server time".

Daylight saving time. If your cron job runs at a fixed clock time (like 2:00 AM), it may run twice or not at all during DST transitions, depending on which direction the clocks move. For jobs where this matters, schedule around the transition times or use UTC throughout.

Day-of-month AND day-of-week interact unexpectedly

When you specify both a day-of-month and a day-of-week, most cron implementations run the job when either condition is true — not both. So 0 9 1 * 1 runs at 9am on the 1st of the month and every Monday, not only on Mondays that fall on the 1st.

Month and day-of-week numbering

Day of week can be 0–7, where both 0 and 7 represent Sunday. Month is 1–12 (1 = January). These are easy to mix up — the builder handles this for you.

Six-Field Cron (with Seconds)

Some systems (Quartz scheduler, many cloud services) add a seconds field at the start:

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

AWS EventBridge and some CI systems use this format. Always check the documentation for the system you're targeting — a five-field expression in a six-field system will be parsed incorrectly.

Special Strings (Where Supported)

Many cron implementations accept readable shortcuts:

@yearly   = 0 0 1 1 *     (once a year)
@monthly  = 0 0 1 * *     (once a month)
@weekly   = 0 0 * * 0     (once a week, Sunday)
@daily    = 0 0 * * *     (once a day at midnight)
@hourly   = 0 * * * *     (once an hour)
@reboot                   (once at startup)

Using Cron in Code

// Node.js — node-cron library
import cron from 'node-cron';

// Run every day at 9:00 AM
cron.schedule('0 9 * * *', () => {
  console.log('Running daily job...');
});

// Run every 15 minutes
cron.schedule('*/15 * * * *', () => {
  sendHeartbeat();
});
# Python — schedule library (simpler) or APScheduler (more powerful)
from apscheduler.schedulers.blocking import BlockingScheduler

scheduler = BlockingScheduler()

@scheduler.scheduled_job('cron', hour=9, minute=0)
def daily_job():
    print('Running daily job...')

scheduler.start()
Build and verify: The Cron Expression Builder generates expressions from dropdowns and shows you the next 5 scheduled run times. Paste any existing expression to get a plain-English description of what it does. Essential for reviewing schedules before deploying them to production.