ToolBoxOnline
Developer

Cron in Production: 6 Habits That Keep Scheduled Jobs From Biting You

The cron line that worked on your laptop fails silently in production. These best practices — and a parser to check them — cover the common traps.

cron best practicescron jobproduction schedulingdevopscrontab

The cron job runs fine on your laptop for a week, so you deploy it and forget it. Three months later someone notices the nightly report stopped at midnight two weeks ago, and the job has been quietly failing ever since. Production cron fails differently from laptop cron: no desktop session, different PATH, overlapping runs, silent output. The good news is the habits that prevent this are short enough to memorize. Here are the six that matter most.

Make Every Job Idempotent

The number-one production killer is a job that runs twice. A slow nightly job that overlaps the next night's run can double-import data, double-send emails, or corrupt a state file — and the second run often looks like a success. Write every job to be safe to run again: guard it with a lockfile so a second instance exits cleanly, or make it idempotent so re-running is harmless. The counter-intuitive part: the safest schedule for a fragile job isn't "less often," it's "often but safely," so a missed run self-heals on the next tick instead of waiting a week.

Pin Everything to UTC

Server timezones lie. A job scheduled at 0 2 * * * runs at 2 AM server-local, and when someone changes the server's timezone for a deploy, the job moves with it — or worse, DST makes it run twice or skip a day. Decide once that your crontab lives in UTC and convert in the app if you need local time. This is the same discipline we covered in our guide to why cron jobs silently fail, and it's the cheapest insurance you'll buy.

Send Output Somewhere You'll See It

Default cron behavior is to mail job output to the owner — which on a headless server means a mailbox nobody opens. Redirect stdout and stderr to a log file per job, add a timestamp prefix, and set up an external health check that pings you only when a run doesn't finish on time. A cron parser is the right first step before any of this: paste the expression in, confirm it means what you think (especially that day-of-month and day-of-week are an OR, not an AND), and check the next ten run times so a "daily at 2 AM" job doesn't turn out to be "every minute." Pair the schedule with a unix timestamp check when you need exact wall-clock times, and use a text sorter to keep log lines greppable when you finally do dig in. Six habits, one sentence each: idempotent, UTC, logged, health-checked, verified in a parser before deploy, and scheduled with the overlap risk in mind. Your future self on pager duty will thank you.

Tools mentioned in this article

Compartir esta herramienta