⏰ Cron Expression Builder & Explainer

Last updated: February 10, 2026

⏰ Cron Expression Builder & Explainer

Build a schedule visually or paste an existing cron expression to get a plain-English explanation and next 5 run times.

Quick Presets
* * * * *
Field Reference
Minute
0–59
Hour
0–23
Day/Month
1–31
Month
1–12
Day/Week
0–6 (Sun=0)
Try an example

Cron Expressions Demystified: What That String of Stars and Numbers Actually Means

If you have ever peeked at a Linux server, a CI/CD pipeline, or a cloud function configuration, you have almost certainly seen something like 0 2 * * * sitting in a schedule field. It looks like someone's cat walked across the keyboard. But once you understand what each piece means, cron expressions become one of the most satisfying little languages in all of computing — five tiny fields that can describe almost any repeating schedule imaginable.

Where Did Cron Come From?

Cron is a job scheduler that has lived inside Unix and Linux systems since the 1970s. The name comes from the Greek word chronos, meaning time. It runs silently in the background, waking up every single minute, checking a table of scheduled tasks (the "crontab"), and running anything whose schedule matches the current time. For fifty years, this same basic mechanism has been backing up databases, sending emails, clearing caches, and doing a million other jobs that humans would rather not do by hand every day.

Today you find cron syntax everywhere: GitHub Actions uses it to schedule automated workflows, AWS Lambda and Google Cloud Scheduler accept it for serverless triggers, Kubernetes uses CronJob objects, and pretty much every CI/CD platform on the planet has borrowed the format. Learning to read and write cron expressions is one of those quietly powerful skills that pays off again and again.

The Five Fields — One at a Time

A standard cron expression has exactly five fields, separated by spaces, in this order:

minute  hour  day-of-month  month  day-of-week

Think of them as increasingly broad time circles, from the smallest (which minute of an hour?) to the largest (which day of the week?). Let's walk through each one.

Field 1 — Minute (0–59). This is which minute of the hour you want the job to run. A 0 means the very top of the hour, 30 means half past, and * means every single minute.

Field 2 — Hour (0–23). This is which hour of the day, using 24-hour time. Midnight is 0, noon is 12, and 11 PM is 23. An asterisk means every hour.

Field 3 — Day of Month (1–31). Which day of the month. 1 means the first, 15 the fifteenth. Useful for payroll runs or monthly reports.

Field 4 — Month (1–12). January is 1, December is 12. Want something to run only in summer? Use 6,7,8.

Field 5 — Day of Week (0–6). Sunday is 0, Monday is 1, all the way to Saturday at 6. Some systems also accept 7 as Sunday — and CI systems sometimes let you write sun, mon, etc.

The Special Characters That Make It Powerful

The real expressiveness comes from a small set of special characters you can use inside any field:

Asterisk * — Means "every possible value." * in the minute field means every minute. * in the month field means every month. This is the most common character in any cron expression.

Slash / (step values) — The / character means "every N." So */15 in the minute field means "every 15 minutes." The * part says "start from the beginning," and /15 says "step by 15." You could also write 0/15 to be explicit that you start at zero — same result.

Comma , (lists) — Lets you specify multiple individual values. 0,30 in the minute field means "at minute 0 and also at minute 30," giving you a task that fires twice per hour. 1,3,5 in the day-of-week field means Monday, Wednesday, Friday.

Hyphen - (ranges) — Specifies a range of values. 1-5 in the day-of-week field means Monday through Friday. 9-17 in the hour field means every hour from 9 AM to 5 PM. You can even combine ranges with steps: 0-30/10 means at minutes 0, 10, 20, and 30.

Reading Real Examples

Let's decode a few expressions you will actually encounter in the wild:

*/5 * * * * — The minute field says "every 5 minutes," everything else is asterisks meaning "any." Result: runs every 5 minutes, 24 hours a day, every day. Classic for health checks or polling tasks.

0 2 * * * — Minute 0, hour 2, everything else wildcard. Runs once a day at 2:00 AM. The standard slot for nightly database backups — chosen because almost nobody is using the app at 2 AM.

0 9 * * 1-5 — Minute 0, hour 9, any day of month, any month, weekdays only (1–5 = Mon–Fri). This runs at 9:00 AM every weekday. Perfect for sending a morning report email.

30 6 1 * * — 6:30 AM on the 1st of every month. Monthly billing runs, month-start reports, subscription renewals — this pattern is everywhere.

0 0 1 1 * — Midnight on January 1st. A yearly task. Useful for archiving old data at the start of a new year or rotating API keys annually.

CI-Style Shortcuts: The @ Aliases

Modern cron implementations — and CI platforms like GitHub Actions — support convenient shortcuts for the most common patterns:

  • @hourly → runs at the start of every hour (same as 0 * * * *)
  • @daily → runs once a day at midnight (same as 0 0 * * *)
  • @weekly → runs every Sunday at midnight (same as 0 0 * * 0)
  • @monthly → runs on the 1st of each month at midnight (same as 0 0 1 * *)
  • @yearly or @annually → runs on January 1st at midnight (same as 0 0 1 1 *)

These are not valid in the original Unix cron but are supported in most modern schedulers. They make intent immediately obvious without needing to decode field positions.

The Tricky Part: Day-of-Month vs Day-of-Week

One genuine source of confusion is what happens when you set both the day-of-month field and the day-of-week field to something other than *. Most cron implementations use an OR rule: the job runs if either condition matches. So 0 0 15 * 5 would run at midnight on the 15th of every month AND also on every Friday. This surprises people who expect an AND relationship. The safe approach: only ever restrict one of the two day fields at a time, and leave the other as *.

Common Mistakes and How to Avoid Them

The most frequent error is off-by-one on hours — forgetting that hours run 0–23, not 1–24. Writing 24 in the hour field usually causes an error or gets silently ignored. Similarly, months run 1–12 (not 0–11 like JavaScript's Date months), and days of the week start at 0 for Sunday, not 1.

Another trap: cron runs in the server's timezone, not yours. A job scheduled for 0 9 * * * on a UTC server runs at 9 AM UTC — which might be 2:30 PM in India or 5 AM in New York. Always be explicit about which timezone your scheduler uses, and consider using UTC internally to avoid daylight-saving time surprises.

Finally, don't schedule many jobs at exactly 0 * * * * or 0 0 * * * if your system has dozens of tasks. The "thundering herd" effect — everything starting simultaneously — can spike CPU and database load. Stagger them: put one job at 0 0, another at 5 0, another at 10 0.

The builder above removes the guesswork entirely. Pick your schedule visually, see the expression update instantly, and verify the next five run times are exactly what you intended — no server surprises required.

FAQ

What do the five fields in a cron expression represent?
Left to right: minute (0–59), hour (0–23), day of month (1–31), month (1–12), and day of week (0–6, where 0 = Sunday). All five are required in standard cron. For example, '30 14 * * 1' means 2:30 PM every Monday.
What does the asterisk (*) mean in a cron field?
An asterisk means 'every possible value' for that field. So '* * * * *' runs every minute of every hour of every day. Once you restrict a field to a specific value, the asterisk in the remaining fields still means 'any,' so '0 9 * * *' runs at 9:00 AM every single day.
How do I schedule a job every 15 minutes?
Use the step syntax with a slash: '*/15 * * * *'. The '*' means start from the beginning of the range (minute 0), and '/15' means step by 15. This fires at minutes 0, 15, 30, and 45 of every hour, every day.
What are @daily, @weekly, and @monthly shortcuts?
These are human-friendly aliases supported by most modern schedulers and CI platforms like GitHub Actions. @daily equals '0 0 * * *' (midnight every day), @weekly equals '0 0 * * 0' (midnight every Sunday), and @monthly equals '0 0 1 * *' (midnight on the 1st of each month). They are not part of the original Unix cron standard but are very widely supported.
Why do both day-of-month AND day-of-week fire instead of combining as AND?
Most cron implementations — including Vixie cron, the most common type — use OR logic when both day-of-month and day-of-week are set to non-asterisk values. So '0 0 15 * 5' fires on the 15th of every month plus every Friday, not only on Fridays that fall on the 15th. To avoid confusion, only restrict one of the two day fields at a time.
Cron runs at a different time than expected — what is going wrong?
Almost always a timezone issue. Cron runs in the timezone of the server or scheduler, which is often UTC. A job scheduled for '0 9 * * *' on a UTC server fires at 9 AM UTC, which is 2:30 PM IST or 5 AM EST. Check your scheduler's timezone setting and convert accordingly — or always write schedules in UTC and document the offset clearly.