Part of theAutomation Suite ⟶
CRON
Cron ExamplesQuick lookup for real workloads

Cron best practices

Cron is a simple, battle-tested way to run recurring jobs. But in production, it's easy to end up with fragile schedules, overlapping jobs, and no visibility into what's actually happening.

These best practices cover how to design cron schedules, write safe commands, and add logging and monitoring so that your jobs stay predictable and debuggable over time.

1. Design clear, intentional schedules

  • Start from the business requirement. "Every weekday at 09:00" or "every 5 minutes" is easier to reason about than an expression you reverse-engineered.
  • Avoid overly clever patterns. Stagger jobs by a few minutes if needed, but prefer expressions that are easy to read at a glance.
  • Be explicit with time zones. Decide whether your cron runs in UTC or local time and document it in comments.
  • Watch the DOM/DOW OR rule. When both day-of-month and day-of-week are restricted, many implementations match if either field matches. That can produce "extra" runs.

Need a refresher on the format? See crontab syntax & format and cron timing & time zones.

2. Write robust cron commands

Cron jobs run in a stripped-down environment. Assuming too much about $PATH, current working directory, or environment variables is a common source of breakage.

  • Use absolute paths. For binaries, scripts, and files (e.g. /usr/bin/python, /usr/local/bin/app).
  • Set a working directory explicitly. Use cd /path/to/app && ... inside the command if your script relies on relative paths.
  • Isolate logic in scripts. Keep crontab lines simple, and put the real work in versioned scripts.
  • Fail fast and with non-zero exit codes. Your scheduler and monitoring can only help if failures bubble up.
# Bad: relies on $PATH and current directory
0 2 * * * backup-db

# Better: absolute paths, explicit cwd, logs to file
0 2 * * * cd /srv/app && /usr/local/bin/backup-db.sh \
  >> /var/log/backup-db.log 2>&1

3. Always log output

"It didn't run" often means "it ran and failed, but no one saw the error." Redirect both stdout and stderr to a log file or centralized logging system.

# Append both stdout and stderr to a log file
*/5 * * * * /usr/local/bin/health-check.sh \
  >> /var/log/health-check.log 2>&1

Learn more in cron logging & logs.

4. Treat cron as code

Hand-editing crontabs on random servers doesn't scale. For anything beyond a single box, treat cron configuration like application code.

  • Check in to version control. Store crontab files, Kubernetes CronJob manifests, or workflow YAMLs in Git.
  • Use consistent naming. Name jobs after the business process, not the implementation detail (e.g. nightly-billing-settlement instead of job1).
  • Separate environments. Different schedules or targets for staging vs. production should be explicit.
  • Automate deployment. Use configuration management or CI/CD to apply changes rather than editing live servers by hand.

5. Monitor, alert, and avoid silent failure

A "fire-and-forget" cron job is fine for side projects, but production workloads need feedback loops.

  • Check exit codes. If a job fails, surface it in your monitoring stack (e.g. by logging a structured error or pinging a healthcheck endpoint).
  • Track last successful run. Store a timestamp in a database, metric, or status file that you can alert on.
  • Set SLOs for key jobs. For "daily" jobs, define what "on time" means and alert if that window is missed.
  • Avoid unbounded retries. Exponential backoff and dead-letter queues are safer than tight cron loops when failures occur.

6. Watch out for overlapping jobs

If a job sometimes takes longer than its interval, you can end up with multiple copies running at once, fighting over the same resources.

  • Use locks. File locks, database row locks, or distributed locks can ensure only one instance runs at a time.
  • Shorten critical sections. Move heavyweight work into queues or workers instead of doing everything in the cron job itself.
  • Increase the interval. Sometimes the simplest fix is to run the job less frequently.

7. Know when not to use cron

Cron is great for simple, time-based triggers. It's not a full workflow engine.

  • Complex dependencies. If you need DAGs, fan-out / fan-in, or conditional branches, consider a workflow orchestrator instead.
  • High-frequency jobs. If you think "every few seconds", cron is usually the wrong tool.
  • Long-running processes. Cron is best for short, bounded tasks. Daemons or workers are better for always-on work.

Related guides & examples