Cron expression for the first of every month
The cron expression 0 0 1 * * runs a job at midnight on the 1st of every month — 12 firings per year. The third field (1) constrains day-of-month to the first; the second 0 is the hour, the leading 0 is the minute. AWS EventBridge needs cron(0 0 1 * ? *) because its day-of-month and day-of-week can’t both be *.
Quick reference
| Platform | Expression |
|---|---|
| Unix / Linux crontab | 0 0 1 * * or @monthly |
| Kubernetes CronJob | 0 0 1 * * or @monthly |
| GitHub Actions | 0 0 1 * * |
| AWS EventBridge | cron(0 0 1 * ? *) |
| Quartz (Java) | 0 0 0 1 * ? |
What if I want the LAST day of the month?
Months have variable length (28, 29, 30 or 31 days), so “last day” is harder than “first”. Three approaches:
Unix cron (no native support):
0 0 28-31 * * /path/to/check-and-run.sh
The script runs every day from the 28th onward and exits early unless tomorrow is the 1st of next month — making the actual job execute only on the true last day:
#!/bin/bash
if [ "$(date -d tomorrow +%d)" = "01" ]; then
exec /usr/local/bin/end-of-month-job
fi
AWS EventBridge: the L extension is supported natively.
cron(0 0 L * ? *)
This runs at midnight on the actual last day of each month — 28, 29, 30, or 31 depending on the month and year.
Quartz: also supports L.
0 0 0 L * ?
Variations
| Schedule | Expression |
|---|---|
| 1st of every month at midnight | 0 0 1 * * |
| 1st of every month at 9 AM | 0 9 1 * * |
| 1st and 15th of every month (mid-month + start) | 0 0 1,15 * * |
| Last day of every month (AWS) | cron(0 0 L * ? *) |
| 1st of every quarter (Jan, Apr, Jul, Oct) | 0 0 1 1,4,7,10 * |
| 1st of January only (annual) | 0 0 1 1 * or @yearly |
How do I use it on each platform?
Linux crontab:
0 0 1 * * /usr/local/bin/monthly-report
Or with the shortcut:
@monthly /usr/local/bin/monthly-report
Kubernetes CronJob:
apiVersion: batch/v1
kind: CronJob
metadata:
name: monthly-report
spec:
schedule: "0 0 1 * *"
timeZone: "UTC"
jobTemplate:
spec:
activeDeadlineSeconds: 3600 # monthly jobs often run long; cap them
template:
spec:
containers:
- name: report
image: my-org/monthly-report:1.0
restartPolicy: OnFailure
AWS EventBridge:
aws events put-rule \
--name monthly-report \
--schedule-expression "cron(0 0 1 * ? *)"
GitHub Actions:
on:
schedule:
- cron: '0 0 1 * *'
Common mistakes
Trying to use day-of-month 31. 0 0 31 * * only fires in months with 31 days — January, March, May, July, August, October, December. February, April, June, September and November are silently skipped. Use L (in AWS/Quartz) or a 28-31 + script pattern (in Unix) instead.
Combining * * 1 * 1 (1st of month AND every Monday). In Unix cron, day-of-month and day-of-week combine as OR, not AND. So this fires every Monday OR on the 1st — not “the 1st only if it’s a Monday”. To get the latter, use a script that filters.
Assuming @monthly works in AWS. AWS EventBridge does not accept @-style shortcuts. Use the explicit form cron(0 0 1 * ? *).
For other schedules see common cron schedules, or build a custom expression with the Cron Expression Builder.
Frequently asked questions
- What is `@monthly` and where does it work?
- `@monthly` is a Vixie-cron alias for `0 0 1 * *` — midnight on the 1st of every month. Accepted in Linux crontab, anacron, GitHub Actions and Kubernetes CronJob. NOT accepted in AWS EventBridge. Use the explicit form when targeting AWS.
- How do I run a job on the LAST day of every month?
- Standard Unix cron has no "last day" syntax. The common workaround: run `0 0 28-31 * *` (so the job fires daily for the last few days), and have the job check `if [ "$(date -d tomorrow +%d)" = "01" ]` — exit early on any day that is not the actual last. AWS EventBridge supports `L` natively: `cron(0 0 L * ? *)` runs on the last day directly.
- Does `0 0 1 * *` skip months that are shorter than expected?
- No — every month has a 1st, so the schedule fires 12 times a year regardless. The trap is at the OTHER end: `0 0 31 * *` (the 31st) only fires in months with 31 days. Use `L` or `28-31` patterns instead.
Need a different schedule?
Build cron expressions for Unix, Kubernetes and AWS — with a human-readable description and the next 5 run times.
Open the Cron Expression Builder →Related
Cron expression for every 5 minutes
The cron expression `*/5 * * * *` runs every 5 minutes in Linux crontab, Kubernetes, GitHub Actions; `cron(*/5 * * * ? *)` in AWS EventBridge.
Cron expression for every 15 minutes
The cron expression `*/15 * * * *` runs every 15 minutes — at :00, :15, :30, :45 — across Linux, Kubernetes, GitHub Actions and AWS.
Cron expression for every hour
The cron expression `0 * * * *` runs once per hour on the hour. Same syntax in Linux, Kubernetes and GitHub Actions; `cron(0 * * * ? *)` in AWS EventBridge.
Cron expression for daily at midnight
The cron expression `0 0 * * *` runs once daily at midnight. Watch the timezone — Kubernetes < 1.25 and AWS EventBridge default to UTC, not local time.
Cron expression for every weekday
The cron expression `0 9 * * 1-5` runs at 9 AM Monday through Friday. AWS uses `cron(0 9 ? * MON-FRI *)` because day-of-week numbering differs.
Cron expression for every Sunday
The cron expression `0 0 * * 0` runs every Sunday at midnight in Unix cron. AWS uses `cron(0 0 ? * 1 *)` because Sunday is `1` in AWS, not `0`.