Skip to content
Free Tool Arena

Developers & Technical · Guide · Coding & Tech

How to Write a Cron Expression

Cron fields, ranges, steps, and lists explained — with 10 ready-to-copy expressions for the schedules you actually need.

Updated April 2026 · 6 min read

Cron expressions are the language scheduled jobs speak — a five-field string that tells a server when to run a task. They are compact, a little cryptic, and once you know how to read them, you can describe almost any schedule in a single line. They also have a reputation for being easy to get wrong, which is how people end up running hourly cleanup jobs every minute by accident.

This guide covers the cron field order, the shortcuts, the operators, and the mistakes that cause real outages. At the end you should be able to read and write cron expressions at a glance — or at least sanity-check the one ChatGPT just gave you.

Advertisement

The five fields of standard cron

A standard cron expression has five space-separated fields, in this order: minute (0–59), hour (0–23), day of month (1–31), month (1–12 or JAN–DEC), day of week (0–6 where 0 and 7 are Sunday, or SUN–SAT). Some systems (Quartz, systemd) add a seconds field at the start or a year field at the end — check your platform’s docs before copy-pasting.

The four operators

* means “every value.” , lists specific values (1,5,10). - defines a range (1-5 = 1,2,3,4,5)./ defines an interval (*/15 in the minute field = every 15 minutes). Combine them freely: 0 9-17/2 * * MON-FRI = every 2 hours from 9am to 5pm on weekdays.

Classic patterns memorized once

Every minute: * * * * *. Every 15 minutes: */15 * * * *. Every hour on the hour: 0 * * * *. Daily at midnight: 0 0 * * *. Daily at 9am: 0 9 * * *. Every Monday at 9am: 0 9 * * MON. First of the month at 3am: 0 3 1 * *. These ten cover 80% of real schedules.

Build expressions visually, then copy

Writing cron expressions by hand is fine for the classic cases, but anything fancier (quarterly reports, alternating weeks, last-day-of-month) is error-prone. Use our cron expression builder to click your way to the pattern you want, then copy the string into your crontab. Sanity-check it with the cron expression explainer which translates any expression back into plain English.

Watch the timezone

Cron runs in the server’s timezone, not yours. A job set for 0 9 * * * runs at 9am server-time. If your server is in UTC and you’re in New York, that’s 4am local in summer, 5am in winter. Always check the system timezone before scheduling anything time-sensitive. Set it explicitly in the cron config (CRON_TZ=America/New_York) if your platform supports it.

The “both weekday AND day of month” gotcha

On most cron implementations, if both day-of-month and day-of-week are specified (not *), the job runs when either matches, not both. So 0 0 15 * MON runs at midnight on the 15th and every Monday — probably not what you meant. If you need “Monday the 15th,” check your system’s docs or handle it in application code.

Don’t schedule jobs too close together

If job A takes 20 minutes and you schedule job B to run 5 minutes after A starts, you can get overlapping executions when A runs long. Use a lock file, a database flag, or a queue with concurrency set to 1. A classic outage is two instances of a nightly import job running simultaneously and corrupting the data.

Log everything — cron is silent by default

A failed cron job won’t email you. It won’t log to stderr in a place you check. It will just silently stop working. Redirect output to a log file: * * * * * /path/to/job >> /var/log/job.log 2>&1. Better: send errors to a monitoring service (Sentry, Datadog) and use a heartbeat service (Dead Man’s Snitch, healthchecks.io) that alerts you when the job stops running.

Stagger high-concurrency jobs

If you have ten cron jobs all set to run at 0 0 * * *, they all fire at midnight and spike your server load. Stagger them: one at 00:00, next at 00:05, next at 00:12. No single busy minute, no thundering herd.

Shortcuts: @hourly, @daily, @reboot

Most cron systems support named shortcuts: @yearly, @monthly, @weekly, @daily (= 0 0 * * *), @hourly (= 0 * * * *), and @reboot (runs once when the system starts). Use them when they match — they’re easier to read and less error-prone than the equivalent five-field expressions.

Test before you trust

Before putting a new cron job into production, run the command directly and confirm it works. Then schedule it for a few minutes from now and watch it fire. Then move it to the real schedule. Jobs that run once a week are the most dangerous — they have the most time to accumulate silent failure between runs.

Related: how to use regex effectively, how to format JSON properly, and what is an API for context on the systems you’re scheduling.