First of the Month Cron Expression
Runs at 00:00 on day 1 of every month.
0 0 1 * * in POSIX cron
Expression
0 0 1 * *Try it in the tester →Field Breakdown
How It Works
Identical to `@monthly`. Fires only when the calendar day is 1, regardless of weekday.
Example Run Times
- Jan 1 00:00:00
- Feb 1 00:00:00
- Mar 1 00:00:00
- Apr 1 00:00:00
- May 1 00:00:00
Frequently Asked Questions
What if both day-of-month and day-of-week are set?
Vixie cron uses the OR rule when both are restricted — the job fires on either match. Quartz uses AND and requires one of the two to be `?`.
0 0 1 * * in Quartz / Spring
Twelve firings a year: midnight on the 1st of each month, whatever weekday that happens to be. Day-of-month is pinned to 1, which pushes the mandatory ? over to the day-of-week field.
Quartz / Spring expression
0 0 0 1 * ?Try it in the tester →At 00:00:00 on day 1 of the month
Unix / POSIX equivalent: 0 0 1 * *
Field Breakdown
Using It with Quartz / Spring
Month-boundary work is billing's home turf — generating invoices, closing accounting periods, resetting monthly quotas and API usage counters, rolling partitioned tables forward. Whether it arrives via @Scheduled(cron = "0 0 0 1 * ?") in a Spring Boot service or a CronTrigger in a standalone Quartz scheduler, treat this trigger as precious: with only one shot per month, configure misfire handling deliberately and alert if the run doesn't complete, because the next natural opportunity is 28 to 31 days away.
Quartz-Specific Notes
- →This is date-driven, so the literal 1 sits in day-of-month and ? fills day-of-week — the opposite arrangement from weekday schedules like 0 0 0 ? * 2-6.
- →Quartz's W token gives a business-day variant: 0 0 0 1W * ? fires on the nearest weekday to the 1st. Since W never crosses a month boundary, a Saturday 1st shifts forward to Monday the 3rd (not back to the previous Friday), and a Sunday 1st fires Monday the 2nd.
- →The mirror-image schedule, last day of the month, needs Quartz's L token (0 0 0 L * ?) — there is no portable five-field cron way to say it.
Frequently Asked Questions
How do I run on the first business day of the month instead?
Use the weekday token: 0 0 0 1W * ?. If the 1st falls on a weekend, Quartz slides the firing to the closest weekday within the same month.
What about the last day of the month?
Quartz supports it directly with L in day-of-month: 0 0 0 L * ? fires on the 28th, 29th, 30th, or 31st as the calendar dictates. Spring's @Scheduled accepts L too from Spring 5.3 onward.
If a deploy keeps the app down over midnight on the 1st, is the run lost?
It misfires. The default policy fires it once as soon as the scheduler is back up; only MISFIRE_INSTRUCTION_DO_NOTHING would make you wait a whole month for the next slot.
0 0 1 * * in AWS EventBridge
Twelve runs a year: midnight UTC as the 1st of each month begins. Here the day-of-month field carries the real constraint (1) while day-of-week takes the required ?, the mirror image of the weekday-based schedules.
AWS EventBridge expression
cron(0 0 1 * ? *)Try it in the tester →At 00:00 UTC on day 1 of the month
Unix / POSIX equivalent: 0 0 1 * *
Field Breakdown
Using It with AWS EventBridge
Configure it as the ScheduleExpression on a rule or Scheduler schedule and point it at month-boundary work: a Step Functions pipeline that closes the books and snapshots billing data via the Cost Explorer API, a Lambda that resets monthly usage quotas in DynamoDB, or an ECS task that archives the prior month's logs from S3 Standard to Glacier. Because the AWS billing period also turns over on the 1st (UTC), this schedule lines up naturally with cost-report generation.
AWS-Specific Notes
- →The 1 sits in day-of-month and the ? in day-of-week — with a concrete day-of-month, day-of-week must be the question mark or validation fails.
- →All twelve yearly runs occur at 00:00 UTC on the 1st regardless of weekday; if you need the last day of the month instead, EventBridge supports L in day-of-month: cron(0 0 L * ? *).
- →A month-boundary job often processes the entire previous month, so a late or duplicated invocation is costly — anchor the processing window to the event's scheduled time field, not to now().
Frequently Asked Questions
How do I run on the first business day of the month rather than the 1st?
Use the W (nearest weekday) token in day-of-month: cron(0 0 1W * ? *) fires on the 1st if it is a weekday, otherwise on the closest weekday within the same month.
Does this align with the AWS billing cycle?
Yes — AWS billing periods roll over at 00:00 UTC on the first of the month, the exact instant this expression fires, though Cost Explorer data for the closed month can take up to 24 hours to finalize.
Can I run at the start of every quarter instead?
Constrain the month field: cron(0 0 1 1,4,7,10 ? *) fires only on January 1, April 1, July 1, and October 1 at midnight UTC.
0 0 1 * * in GitHub Actions
Day-of-month pinned to 1: the workflow fires at 00:00 UTC on the first calendar day of each month, twelve times a year. On GitHub Actions this is the natural trigger for anything aligned to billing periods, monthly releases, or reporting cycles.
GitHub Actions expression
0 0 1 * *Try it in the tester →At 00:00 UTC on day 1 of the month
Unix / POSIX equivalent: 0 0 1 * *
Field Breakdown
Using It with GitHub Actions
Placed in workflow YAML as on: schedule: - cron: "0 0 1 * *", the monthly tick drives version-bump-and-tag release workflows, monthly contributor or download reports generated with the GitHub API, and rotation of secrets or tokens on a monthly compliance cadence. Remember the alias forms are off the table — "@monthly" is not documented for the schedule event, so the five explicit fields are required. With only 12 runs a year, pairing this trigger with workflow_dispatch for dry runs is practically mandatory.
GitHub-Specific Notes
- →Fires regardless of weekday — the 1st can be a Saturday or a public holiday, so monthly release workflows that need human follow-up often run on the first Monday instead, which requires extra logic since 5-field cron cannot express "first Monday" directly.
- →Midnight UTC on the 1st means the run lands on the last day of the previous month in every timezone west of UTC — a monthly report kicked off then may bucket data into the wrong month if the job assumes local dates.
- →Twelve ticks a year makes this the schedule most likely to be killed unnoticed by the 60-day public-repo inactivity rule — two quiet months is all it takes.
Frequently Asked Questions
How do I run on the LAST day of the month instead of the first?
GitHub's 5-field cron has no L token (that's a Quartz/EventBridge feature). Schedule 0 0 28-31 * * and add a first step that exits unless tomorrow is the 1st — e.g. [ "$(date -d tomorrow +%d)" = "01" ] || exit 0.
How do I run on the first Monday of the month instead of the 1st?
Careful: 0 0 1-7 * 1 does NOT work — cron ORs the two day fields, so that fires on days 1-7 AND on every Monday. Schedule 0 0 1-7 * * instead and add a job step that exits unless date +%u prints 1.
Will the run on March 1st include February 29th data?
That's up to your job, not the schedule — but note the run starts at 00:00 UTC on the 1st, so anywhere west of UTC it is still the last day of the prior month locally. Compute report windows in UTC to avoid off-by-one-day month boundaries.