Run Monthly Jobs on the 28th at Midnight | CronBase

cron expression Standard
$ 0 0 28 * *

At midnight on the twenty-eighth day of every month

The `0 0 28 * *` cron schedule executes a task exactly at midnight on the twenty-eighth day of every single month. This specific timing is highly reliable for monthly recurring billing, financial ledger reconciliation, and system report generation, as the twenty-eighth is guaranteed to exist in every month of the calendar year, including February.

Minute
0
Hour
0
Day of Month
28
Month
*
Day of Week
*
How it works

Next 5 Runs

  • in 2d 3h
  • in 33d 3h
  • in 64d 3h
  • in 94d 3h
  • in 125d 3h

* Tools

Code & Implementations

Bash
#!/usr/bin/env bash
# Production Bash script designed to run monthly on the 28th.
# Uses a lock file to prevent concurrent executions.
set -euo pipefail
LOCKFILE="/var/lock/monthly_ledger_run.lock"
exec 200>"$LOCKFILE"
flock -n 200 || { echo "Error: Another instance is running." >&2; exit 1; }

echo "[$(date -u)] Starting monthly financial ledger processing..."
# Call downstream service or run database cleanup
if ! curl -f -s -X POST https://api.internal/v1/ledger/close; then
    echo "Error: Ledger closure API call failed." >&2
    exit 1
fi
echo "[$(date -u)] Monthly task completed successfully."
Setup notes

Save the script to /usr/local/bin/monthly-ledger.sh, run chmod +x, and add 0 0 28 * * /usr/local/bin/monthly-ledger.sh to the system crontab.

Last verified:

Partner BetterStack

Monitor this schedule in production

Get alerted the moment this cron job fails, is late, or doesn't run. BetterStack tracks execution, duration, and output — no infrastructure required.

Platform Equivalents

AWS EventBridge

Standard cron expressions often need conversion for AWS EventBridge schedules.

EventBridge Rule
cron(0 0 28 * ? *)

Systemd Timer

OnCalendar*-*-28 00:00:00

my-task.timer
[Unit]
Description=Timer for cron expression: 0 0 28 * *

[Timer]
OnCalendar=*-*-28 00:00:00
Persistent=true

[Install]
WantedBy=timers.target

Last verified:

Frequently Asked Questions

Why is the 28th chosen instead of the 30th or 31st for monthly jobs?

The 28th is the highest day number that exists in every single month of the year, including February. Choosing the 30th or 31st would require complex custom logic to handle shorter months, making the 28th the safest choice for consistent monthly intervals.

How does Daylight Saving Time (DST) affect a midnight cron job?

If your server runs on local time, DST transitions can cause the midnight job to run twice or be skipped entirely. To prevent this, configure your cron daemon or application runtime to execute in Coordinated Universal Time (UTC).

What happens if the monthly job fails to run due to server downtime?

Standard cron has no built-in catch-up mechanism. You should use a tool like anacron, implement a state-based database flag to track execution, or use a scheduling framework with 'misfire' instructions to run missed executions upon recovery.

How can I prevent database connection timeouts during this heavy monthly run?

Introduce a random startup delay (jitter) of several minutes before the main execution logic begins. This staggers the initial database connections and prevents resource starvation, especially when multiple microservices trigger concurrent monthly tasks.

Can I restrict this monthly job to run only on weekdays?

Standard cron does not easily support '28th of the month AND only weekdays' in a single expression because day-of-month and day-of-week fields act as an OR relationship. You must handle this filter programmatically within your script or application code.

* Explore

Related expressions you might need

Last verified:

Was this helpful?