📅 Cron Expression Explainer

Last updated: November 20, 2025

Cron Expression Explainer

Paste any 5-field cron expression (or a shorthand like @daily) to see what it means and when it will next run.

Quick:
8 runs

What Is a Cron Expression, and Why Should You Care?

If you have ever wondered how your server sends that weekly newsletter, clears its log files every morning at 3 AM, or backs up your database without anyone pressing a button — the answer is almost always a cron job. And at the heart of every cron job is a short, cryptic-looking string called a cron expression. It looks something like this: 0 9 * * 1-5. To someone who has never seen one before, that string might as well be a cat walking across a keyboard. But once you decode the pattern, it becomes completely readable — and you will start seeing cron expressions everywhere.

The Five Fields That Rule Your Schedule

Every standard cron expression has exactly five fields, separated by spaces. Each field represents a unit of time, and they always appear in the same order: minute, hour, day of month, month, day of week. A quick way to remember the order is the phrase "Make Haste, Don't Miss Deadlines" — though to be honest, once you use cron a few times, the order just sticks.

The minute field ranges from 0 to 59. The hour field goes from 0 (midnight) to 23. Day of month is 1 through 31. Month is 1 through 12. And day of week runs from 0 (Sunday) to 6 (Saturday), with some systems also accepting 7 as a second representation of Sunday.

When you put a * in a field, it means "every possible value" — every minute, every hour, every day. So * * * * * means "run this every single minute, all day, every day, forever." That is the most extreme version. In practice, you will usually lock down at least a few fields.

Reading Your First Cron Expression Like a Pro

Let's take 0 9 * * 1-5 and walk through it field by field.

The first field is 0 — that is minute zero, meaning exactly at the top of the hour. The second field is 9 — the ninth hour, which is 9 AM. The third field is * — every day of the month. The fourth field is also * — every month. The fifth field is 1-5 — Monday through Friday (days 1 to 5).

Put it together: "Run at 09:00 AM, Monday through Friday, every month, every year." That is a classic workday morning job — maybe sending a daily standup reminder or kicking off a build pipeline.

Special Characters That Give Cron Its Power

Beyond simple numbers and asterisks, cron expressions have four special characters that let you express complex schedules in very few characters.

The comma creates a list. 0 9,17 * * * means "at 9 AM and at 5 PM every day." You are listing two specific values in the hour field.

The hyphen defines a range. 0 9 * * 1-5 uses a hyphen to mean "days 1 through 5," which is Monday through Friday. You can use ranges in any field.

The forward slash creates a step. */5 * * * * means "every 5 minutes." The asterisk before the slash means "starting from the beginning of the range," and the 5 means "step by 5." So you get minutes 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, and 55. You can also do 10-30/5 to mean "every 5 minutes between minute 10 and minute 30."

Understanding these four characters — *, ,, -, and / — is basically the whole language. Everything else is just applying them in different combinations.

Shorthand Presets for the Most Common Cases

Because certain schedules come up so often, many cron systems support named shortcuts. Instead of 0 0 * * *, you can write @daily. Instead of 0 * * * *, you can use @hourly. The full list of common shortcuts includes @yearly, @monthly, @weekly, @daily, @midnight, and @hourly. There is also @reboot, which runs the job once when the system starts up — that one has no regular schedule, so you cannot calculate future run times for it.

These shortcuts are not available in every cron implementation, but they work in most modern Linux systems and popular scheduling libraries.

Why Timezones Matter More Than You Think

Here is a trap that catches even experienced developers: cron runs in whatever timezone the system clock is set to. If your server is set to UTC and you write 0 9 * * * thinking it means "9 AM for my users in New York," you are going to be surprised. In UTC, 9 AM is 5 AM Eastern, or 2:30 PM in India Standard Time.

This becomes a real problem when you are running jobs across multiple servers in different regions, or when your team is distributed globally. The safest habit is to always think in UTC for your servers, and then mentally convert when you are writing the expression. Or better yet, use a tool that shows you the next run times in your local timezone — which is exactly what this explainer does.

Some modern cron systems like AWS EventBridge and Kubernetes CronJobs let you specify a timezone directly in the job configuration, separate from the server clock. That eliminates the confusion entirely, and it is worth using when available.

Practical Examples You Will Actually Use

A few cron expressions appear in almost every production environment. 0 2 * * * is the classic "run at 2 AM every night" — great for database backups, cleanup jobs, or anything that should not compete with daytime traffic. */15 * * * * runs every 15 minutes, which is popular for health checks, cache warming, or syncing data from an external API. 0 0 1 * * runs at midnight on the first of every month — useful for generating monthly reports or resetting usage counters.

For more advanced cases, 0 8-18 * * 1-5 runs at the top of every hour during business hours on weekdays. And 30 6 1,15 * * runs at 6:30 AM on the 1st and 15th of every month — perfect for a bimonthly billing cycle task.

A Common Gotcha: DOM vs. DOW

One quirk worth knowing: if you specify both a day-of-month AND a day-of-week restriction in the same expression, most cron implementations treat them as an OR, not an AND. So 0 0 1 * 5 means "midnight on the 1st of the month, OR midnight on every Friday" — not "midnight on Fridays that fall on the 1st." This surprises a lot of people. If you need an AND condition (only when a specific date falls on a specific weekday), you usually have to handle that logic inside your script rather than in the cron expression itself.

Getting comfortable with cron expressions is one of those small skills that pays off constantly. Once you can read and write them fluently, you stop needing to copy-paste from Stack Overflow and start writing them from scratch in seconds. Use the explainer above to check your work, explore edge cases, and confirm your schedule actually runs when you expect it to — especially across timezones.

FAQ

What do the five fields in a cron expression mean?
The five fields, from left to right, are: minute (0–59), hour (0–23), day of month (1–31), month (1–12), and day of week (0–6, where 0 and 7 both mean Sunday). A * in any field means 'every possible value' for that unit.
What does */5 mean in a cron expression?
The slash character defines a step interval. */5 in the minute field means 'every 5 minutes' — the scheduler fires at minutes 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, and 55. You can use this pattern in any field, for example */2 in the hour field means every 2 hours.
Why do cron times look wrong in my timezone?
By default, cron runs in the server's system timezone, which is often set to UTC. If you write 0 9 * * * expecting a 9 AM local job but your server is in UTC, it will fire at 9 AM UTC — which could be the middle of the night or afternoon depending on your location. Always check what timezone your server runs in, and use a timezone-aware tool to verify your upcoming run times.
What is the difference between @daily, @midnight, and 0 0 * * *?
All three are exactly equivalent and mean 'run once a day at midnight (00:00).' The @daily and @midnight shorthands are just more readable aliases for the same five-field expression. Similarly, @hourly equals 0 * * * *, @weekly equals 0 0 * * 0, and @monthly equals 0 0 1 * *.
Can I specify both a day of month and a day of week in the same expression?
Yes, but be careful — most cron implementations treat it as OR, not AND. For example, 0 0 1 * 5 fires at midnight on the 1st of every month AND at midnight every Friday, not only on Fridays that happen to fall on the 1st. If you need an AND condition, you have to check the calendar logic inside your script.
How do I run a cron job every weekday at 9 AM and 5 PM?
Use the expression 0 9,17 * * 1-5. The comma in the hour field creates a list of two specific hours (9 and 17, which is 5 PM), and 1-5 in the day-of-week field restricts it to Monday through Friday. You can paste this into the explainer above to see the exact upcoming timestamps in your timezone.