Guide

Cron Expressions Explained: Fields, Syntax & Examples

By ExpTool Editorial Team · Published Recently

What is a cron expression, really?

It's a five-field string that tells a computer when to run a job: minute, hour, day of the month, month, and day of the week. The expression 0 9 * * 1 means "at 9:00 AM, every Monday." Once you can read those five slots left to right, you can decode any schedule ever written — and write your own without keeping a cheatsheet open in the next tab.

Cron looks trivially simple until it quietly isn't — usually at 2 AM when a job fires at the wrong hour. The good news: the whole system fits in your head in about ten minutes. Let's do that.

The five fields, from zero

Read left to right. Each position has its own allowed range:

  • Minute (0–59) — the minute past the hour
  • Hour (0–23) — the hour of the day, 24-hour clock
  • Day of month (1–31) — which date
  • Month (1–12) — which month; most systems also accept JAN–DEC
  • Day of week (0–7) — which weekday; both 0 and 7 mean Sunday

So 30 14 * * * breaks down as: minute 30, hour 14, any day, any month, any weekday — "2:30 PM every day." And 0 0 1 1 * is minute 0, hour 0, day 1, month 1, any weekday — "midnight on January 1st," once a year. See? You're already reading cron.

One thing to file away: some systems (notably Quartz, used in Java shops) add a *seconds* field at the front, making it six or seven fields. If your expression has six slots and nothing makes sense, you're probably looking at Quartz format. Standard Unix cron is five. Know which flavor you're writing before you trust your reading.

The special characters: *, /, ,, -

Four symbols do all the heavy lifting:

  • ***** means "every." * in the minute field = every minute.
  • / means "step." */15 in the minute field = every 15 minutes (0, 15, 30, 45). 0 */2 * * * = every 2 hours, on the hour.
  • , means "and." 0 9 * * 1,3,5 = 9 AM on Monday, Wednesday, and Friday.
  • - means "through." 0 9 * * 1-5 = 9 AM Monday through Friday. This is the one you'll use constantly — 1-5 is how everyone writes "weekdays."

Combine them freely: */10 9-17 * * 1-5 reads as "every 10 minutes, between 9 AM and 5 PM, Monday through Friday." Dense, but completely logical once the pieces click.

Five schedules you'll actually use

Theory is nice; here are the patterns that cover 90% of real life:

  • **0 2 * * *** — the 2 AM daily backup. Middle of the night, nobody's awake, systems are idle. The most common cron expression in existence, probably.
  • ***/15 * * * *** — every 15 minutes. Health checks, queue workers, cache refreshes. If something needs to happen "regularly" but not constantly, this is the default.
  • **0 9 * * 1-5** — 9 AM on weekdays. The daily report email, the standup reminder, the "sync the thing" job. Business hours live in this expression.
  • **0 0 1 * *** — midnight on the 1st of every month. Invoices, monthly rollups, subscription renewals. Note the day-of-month field doing the work while day-of-week stays *.
  • **30 6 * * 0** — 6:30 AM every Sunday. Weekly cleanup, log rotation, the newsletter build. Sunday morning is the traditional "nobody will notice" slot.

Building something custom? The cron expression generator lets you click through plain-English options and produces the expression — handy for double-checking the ones you write by hand.

The gotchas that bite everyone

The day-of-month OR day-of-week trap. This is the classic. When you restrict *both* the day-of-month and day-of-week fields, cron runs the job when *either* matches — not both. So 0 0 1 * 1 does NOT mean "midnight on Mondays that fall on the 1st." It means "midnight on the 1st of the month AND every Monday." I've seen this one cause duplicate invoice runs. If you want "the first Monday of the month," you need 0 0 1-7 * 1 — days 1–7 that are also Monday.

Sunday is two numbers. Both 0 and 7 mean Sunday in most implementations. 0 0 * * 0 and 0 0 * * 7 are the same schedule. Pick one and be consistent so the next person reading your crontab doesn't wonder.

The server's timezone, not yours. Cron runs in the system's local time. Your laptop says 2 AM; the server in another region says something else entirely. Every "why did this run at a weird hour" mystery I've debugged came down to timezone. Always confirm what timezone the machine thinks it's in.

Environment minimalism. Cron jobs run with a bare-bones environment — your shell aliases, PATH additions, and env vars don't exist there. Use absolute paths (/usr/bin/python3, not python3) and set any env vars explicitly.

Frequently asked questions

How do I schedule something every 90 minutes?

Honestly? Cron can't express that cleanly — the hour field doesn't divide evenly by 1.5. The practical fix: run every 30 minutes (*/30 * * * *) and have your script check whether 90 minutes have elapsed since its last run. Most people go with the script-side check.

What's the difference between 0 and 7 for Sunday?

Nothing, functionally — both mean Sunday in Vixie cron and most modern implementations. It's purely a readability choice. Just be aware that some older or exotic systems only accept 0–6, so 0 is the safer bet if you're writing for maximum portability.

My cron job isn't running. Where do I look?

The usual suspects, in order: (1) the cron daemon itself isn't running — check with systemctl status cron or equivalent; (2) timezone mismatch between you and the server; (3) the day-of-month/day-of-week OR trap above; (4) environment issues — relative paths or missing env vars, since cron's environment is nearly empty; (5) permissions on the script. And always have the job log its output somewhere: append >> /var/log/myjob.log 2>&1 until you trust it.

Can I test a cron expression without waiting for it to fire?

Yes — that's exactly what validators and generators are for. Paste the expression in and it will list the next several fire times in plain language, so you can confirm "every weekday at 9" actually means what you think before it goes live. Much cheaper than discovering the mistake from a 3 AM page.

Related tools

You can also use Explore all free online tools and Read more helpful articles as part of your workflow.

Using a cron expression syntax can make this task easier and more efficient when you need a simple online solution.

A cron expression syntax is especially useful when you want a quick browser-based workflow.

Featured Tools Mentioned in this Guide

Cron Expression Generator →