The easiest way is to simply create three separate cron jobs:
0 0 30 4,6,9,11 * command
0 0 31 1,3,5,7,8,10,12 * command
0 0 28 2 * command
Some cron implementations support the L special value for day-of-month — which is precisely the last day of the month.
0 0 L * *Standard Unix crontab has no concept of “last day of the month”. The portable workaround is to enumerate the months by their length: 30-day months (April, June, September, November), 31-day months (January, March, May, July, August, October, December), and February separately. The 28 in the February line is a simplification — for leap years use 0 0 28,29 2 * and let the script handle whichever day actually exists.
The L modifier (“last”) is the right answer whenever your scheduler supports it. Each major implementation differs slightly: Quartz, AWS EventBridge, robfig/cron in Go, Jenkins, Azure Functions (NCRONTAB) and dragonmantank/cron-expression for PHP all support L, but with subtly different syntax for “0 0 L * *”. Pick the dialect that matches your runtime.
A common alternative is the “run daily, exit unless tomorrow is the 1st” trick: 0 0 28-31 * * [ "$(date -d tomorrow +%d)" = "01" ] && command. It needs no L support and works on any cron, but the one-liner is brittle and platform-dependent — most teams prefer the multi-cron approach above.
Read the dedicated guide: Cron expression for the last day of the month.
Other answers and worked examples for the most confusing cron expressions.
Ready to schedule it?
WordPress, Shopify, Railway, Cloud Run, Vercel, HubSpot, Ghost, your own box. If it answers HTTP, Crontap can drive it on a clock you can read, in the timezone that actually matters, and page you when something breaks.
Free forever tier ・ No credit card required
Schedule
“every 5 minutes”
Next run
in 23s
Permalink: https://tool.crontap.com/help/cron-job-expression-every-last-day-of-the-month