Cron Expression
Builder & Explainer

Type any cron expression — get an instant plain-English description, next 10 execution times with timezone support, and 30+ templates. Validates for Unix, Kubernetes, GitHub Actions, and AWS EventBridge.

At 09:00 AM, Monday through Friday

Valid

Next 10 executions

  1. 1Thu, Apr 9, 2026, 9:00 AM
  2. 2Fri, Apr 10, 2026, 9:00 AM
  3. 3Mon, Apr 13, 2026, 9:00 AM
  4. 4Tue, Apr 14, 2026, 9:00 AM
  5. 5Wed, Apr 15, 2026, 9:00 AM
  6. 6Thu, Apr 16, 2026, 9:00 AM
  7. 7Fri, Apr 17, 2026, 9:00 AM
  8. 8Mon, Apr 20, 2026, 9:00 AM
  9. 9Tue, Apr 21, 2026, 9:00 AM
  10. 10Wed, Apr 22, 2026, 9:00 AM

Cron Expression FAQ

Why do day-of-month and day-of-week act as OR instead of AND?
This is one of the most misunderstood aspects of cron. When both day-of-month and day-of-week are set to non-wildcard values, the job fires when either condition matches — not both. For example, 0 0 15 * 5 fires on the 15th of every month and also every Friday, not just Fridays that land on the 15th. This is defined in POSIX. If you need AND logic, check the date inside your script.
What's the difference between <code>*/5</code> and <code>0/5</code> in the minute field?
*/5 means "every 5 minutes starting from 0" — fires at :00, :05, :10, :15 … :55. 0/5 is Quartz syntax meaning the same thing (start at 0, step by 5). In standard Unix cron, 0/5 is not valid — use */5. In Quartz (Java schedulers), both work identically. The distinction matters when migrating between systems.
Why isn't my cron job running at exactly the scheduled time?
Cron has minute-level granularity — it cannot schedule sub-minute precision. Even at the minute boundary, there is a small delay (typically 1–10 seconds) while the scheduler wakes up and forks the process. On GitHub Actions, scheduled workflows are explicitly "best effort" and can be delayed by 30+ minutes during high load. On Kubernetes, the controller reconciliation loop adds up to ~10 seconds of jitter. If exact timing matters, use a dedicated task scheduler with sub-second support.
What timezone is my cron job using, and how do I set a specific one?
Standard Unix/Linux cron uses the system timezone by default. You can override per-job with the CRON_TZ or TZ environment variable: CRON_TZ=America/New_York 0 9 * * *. Kubernetes CronJobs default to UTC; set spec.timeZone: "America/New_York" (supported from K8s 1.27+, requires feature gate on 1.24–1.26). GitHub Actions always runs in UTC with no override. AWS EventBridge also runs in UTC only.
How do I run a cron job on the last day of every month?
Standard Unix cron has no "last day" syntax. Common workarounds: (1) use 28-31 in the day-of-month field and check [ "$(date +%d)" = "$(date -d tomorrow +%d)" ] && exit 0 in your script to bail on non-last days, (2) use 0 0 28,29,30,31 * * and guard inside the script. Quartz cron and AWS EventBridge both support the L modifier natively: 0 0 L * ? (Quartz) or cron(0 0 L * ? *) (AWS).
Can I express "every 2 weeks" in cron?
Not directly. Cron has no "every N weeks" primitive. Workarounds: (1) use 0 0 1,15 * * to fire on the 1st and 15th (roughly biweekly), (2) use a wrapper script that checks $(( $(date +%s) / 604800 % 2 )) and exits if it's the wrong week, (3) use a higher-level scheduler like AWS EventBridge Scheduler, which supports flexible time windows.
What does <code>?</code> mean in AWS EventBridge expressions — and why is it required?
EventBridge's 6-field cron engine cannot evaluate both day-of-month and day-of-week simultaneously — exactly one of them must be set to ? (meaning "don't care"). If you write cron(0 9 * * MON-FRI *), EventBridge rejects it with a validation error. The correct form is cron(0 9 ? * MON-FRI *). This is unique to EventBridge — standard Unix cron doesn't use ? at all.
What's the maximum frequency I can schedule on GitHub Actions?
GitHub enforces a hard minimum of 5 minutes between scheduled runs. Expressions like * * * * * (every minute) or */2 * * * * (every 2 minutes) are silently throttled. In practice, even */5 may not fire on time during high-load periods. GitHub also disables scheduled workflows after 60 days of repository inactivity — you'll receive an email to re-enable them.
How do I prevent a cron job from overlapping if one run takes longer than the interval?
Unix cron provides no built-in concurrency protection — a new instance starts regardless of whether the previous one finished. Solutions: (1) use flock: */5 * * * * flock -n /tmp/myjob.lock /path/to/script.sh, (2) use run-one on Ubuntu/Debian, (3) use a PID file in your script. On Kubernetes, set concurrencyPolicy: Forbid in your CronJob spec. GitHub Actions has no equivalent — overlapping runs are allowed unless you add explicit guards.
How do I debug a cron job that stopped running without any errors?
Work through this checklist: (1) Check the cron daemon is running: systemctl status cron or service crond status. (2) Check logs: /var/log/syslog, /var/log/cron, or journalctl -u cron. (3) Verify the user's crontab: crontab -l — make sure the expression is saved. (4) Check environment: cron runs with a minimal PATH. Add PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/bin at the top of your crontab. (5) Redirect output: * * * * * /path/to/job >> /tmp/job.log 2>&1 to capture stdout and stderr.
What's the difference between Standard and Quartz cron — and which should I use?
Standard = 5 fields: minute hour day-of-month month day-of-week. Quartz = 6 fields — adds a seconds field at position 1 (so the order is second minute hour dom month dow). Quartz is used in Java schedulers (Spring Batch, the Quartz Scheduler library). AWS EventBridge is NOT Quartz — it adds a year field at the end (min hr dom mon dow year) and is its own distinct format. If you're on Unix/Linux, Kubernetes, or GitHub Actions, use Standard. Toggle between modes using the Standard / Quartz chips at the top of the builder.