Skip to main content
Tools Harbor

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

PlatformExpression
Unix / Linux crontab0 0 1 * * or @monthly
Kubernetes CronJob0 0 1 * * or @monthly
GitHub Actions0 0 1 * *
AWS EventBridgecron(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

ScheduleExpression
1st of every month at midnight0 0 1 * *
1st of every month at 9 AM0 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