Monthly at 9 AM Cron Expression
Runs on the 1st of every month at 09:00.
0 9 1 * * in POSIX cron
Expression
0 9 1 * *Try it in the tester →Field Breakdown
How It Works
Day-of-month pinned to 1, hour pinned to 9 — fires once per month at 09:00 on the 1st, regardless of weekday.
Example Run Times
- Jan 1 09:00:00
- Feb 1 09:00:00
- Mar 1 09:00:00
- Apr 1 09:00:00
- May 1 09:00:00
Frequently Asked Questions
Why fire at 9 AM instead of midnight?
Reports that humans will read are easier to monitor during business hours. Anomalies surface immediately instead of waiting until the next morning.
0 9 1 * * in Quartz / Spring
Twelve firings a year: 09:00 on the first day of each month, whatever weekday the calendar deals. Unlike midnight-of-the-1st schedules, this one is timed for human eyes — the report lands as the month's first workday-ish morning begins.
Quartz / Spring expression
0 0 9 1 * ?Try it in the tester →At 09:00:00 on day 1 of the month
Unix / POSIX equivalent: 0 9 1 * *
Field Breakdown
Using It with Quartz / Spring
Month-opening business output is the typical payload: last month's KPI summary mailed to leadership, monthly invoice batches released after overnight period-close completes, quota counters reset in time for the new month's first transactions. Declare it with @Scheduled(cron = "0 0 9 1 * ?") in Spring or via CronScheduleBuilder in Quartz. The nine-hour offset from midnight is load-bearing — it leaves the entire night of the 1st for accounting close-out jobs to finish before this trigger reads their results.
Quartz-Specific Notes
- →The literal 1 occupies day-of-month and ? fills day-of-week; reversing them (0 0 9 ? * 1) is valid Quartz but means 9 AM every Sunday — twelve runs a year becomes fifty-two.
- →With one opportunity per month, a swallowed exception costs thirty days; surround the job body with explicit failure alerting rather than relying on someone noticing a missing email.
- →Roughly a third of these firings land on a Saturday or Sunday in any given year. If the audience won't read weekend mail, either accept the delay or move to an nth-weekday schedule.
Frequently Asked Questions
Can I send this on the first Monday of the month instead, so it never hits a weekend?
Yes — Quartz's # token handles nth-weekday schedules natively: 0 0 9 ? * 2#1 fires at 09:00 on each month's first Monday. Note the constraint moves to day-of-week, so day-of-month becomes ?.
The report references "last month" — which month does the January 1st run cover?
Whatever your code computes; the trigger only supplies the start moment. The robust pattern is deriving the period from the fire time (previous month of the trigger's scheduled fire time), so a misfired run executed late still reports on the intended month.
0 9 1 * * in AWS EventBridge
One fire per month at 09:00 UTC on the 1st — the daylight-hours cousin of the midnight first-of-month schedule. The nine-hour offset from the month boundary is the whole point: overnight pipelines have closed out the old month before this trigger asks anyone to look at it.
AWS EventBridge expression
cron(0 9 1 * ? *)Try it in the tester →At 09:00 UTC on day 1 of the month
Unix / POSIX equivalent: 0 9 1 * *
Field Breakdown
Using It with AWS EventBridge
Schedule the human-facing monthly artifacts here: a report generator that renders last month's numbers and posts them to the leadership channel mid-morning European time, monthly quota and entitlement resets that should be observable while support staff are online to field "why did my counter reset" tickets, or the kickoff of a month-opening checklist workflow in Step Functions. Running at 09:00 rather than 00:00 also sidesteps the crowd of jobs that pile onto the first midnight of the month.
AWS-Specific Notes
- →The AWS billing period flips at 00:00 UTC on the 1st, nine hours before this fires — early-month cost data is more settled by then, though Cost Explorer can still take longer to fully finalize a closed month.
- →09:00 UTC on the 1st is 04:00–05:00 US Eastern and a constant 18:00 in Tokyo; "mid-morning" only holds for Europe and Africa.
- →The 1st lands on every weekday over time, so three or four runs a year occur on weekends — acceptable for automated resets, awkward for reports expecting same-day readers.
Frequently Asked Questions
Can I run on the first Monday of the month at 9 instead of the 1st?
Yes — move the constraint to day-of-week with the nth-occurrence token: cron(0 9 ? * 2#1 *). Day-of-month then takes the ?, and the run always lands on a weekday.
Why not just run at midnight when the month rolls over?
At 00:00 UTC on the 1st the previous month's data is seconds old and most nightly aggregation hasn't run. A 09:00 fire consumes finished pipelines, and its failures page someone who is awake.
0 9 1 * * in GitHub Actions
Once a month, on the 1st, at 09:00 UTC — a month-opener timed for the European morning rather than the stroke of midnight. The nine-hour offset from 00:00 is the whole point: by 09:00 UTC, midnight-anchored month-end processes elsewhere have had the entire night to finish.
GitHub Actions expression
0 9 1 * *Try it in the tester →At 09:00 UTC on day 1 of the month
Unix / POSIX equivalent: 0 9 1 * *
Field Breakdown
Using It with GitHub Actions
Defined as on: schedule: - cron: "0 9 1 * *" in workflow YAML on the default branch, this slot generates the previous month's summary just in time for the first working morning: contributor and traffic reports built from the GitHub API, a freshly opened tracking issue for the new month's release, or a billing roll-up that needs upstream finance exports to have landed first. With just twelve executions a year, a dry-run path matters — adding workflow_dispatch costs one line and saves a month of waiting to verify a fix.
GitHub-Specific Notes
- →By 09:00 UTC on the 1st, the new month has already begun across all of Europe and the continental US (it is 1:00-5:00 AM there) — though Hawaii and other far-western zones are still finishing the old month's last evening.
- →Compared with a midnight-on-the-1st schedule, the nine-hour delay gives any month-end close process running overnight a generous head start before this job reads its output.
- →The 1st falls on whatever weekday it pleases — over time, about 28% of these runs will land on weekends, which matters if the report expects same-day human eyes.
Frequently Asked Questions
What happens when the 1st is a Saturday or Sunday?
The workflow runs anyway — cron has no weekday opinion when the day-of-month field is doing the selecting. If the output needs a human the same day, either accept the Monday pickup or add logic that defers notification to the next weekday.
Can the job assume last month's data is complete when it runs?
In UTC terms, yes — the prior month ended nine hours earlier. But completeness really depends on your upstream pipelines: if a finance export finishes at 06:00 UTC on the 1st, this 09:00 run clears it; verify the dependency rather than assuming.