/
July 24, 20268 min read

Cron vs. Modern Schedulers: When Plain Cron Is (and Isn't) Enough

Scheduled Taskcronsimple, fixed-timesystemd timerdependencies + logsworkflow enginemulti-step + retriescloud schedulerno server to runpick the simplest one that actually fits

Cron has survived fifty years of software fashion cycles for a reason: for the overwhelming majority of scheduled tasks, it's still the simplest tool that actually works. But 'still relevant' isn't the same as 'always the right choice,' and knowing where cron's limits actually are — rather than reaching for a heavier tool out of habit, or sticking with cron out of inertia — is worth thinking through deliberately.

What cron is actually good at

Cron's entire value proposition is that it does one thing — run a command at a fixed point in time — with almost no moving parts, no dependencies, and a syntax that's been stable and documented since the 1970s. For a huge share of real-world scheduled work — nightly backups, periodic cache warms, log rotation, sending a daily digest — that's the entire job, and anything more elaborate is pure overhead.

The tradeoff is that cron has no concept of anything beyond 'run this at this time': no retries, no dependency ordering between jobs, no visibility into whether a run succeeded, and no distributed coordination if the same crontab is deployed to more than one machine.

When systemd timers earn their extra complexity

systemd timers are worth the two-file overhead specifically when a job needs to depend on something else — start only after a database service is confirmed up, for instance — or when you want structured, queryable logs via journalctl without building that yourself. If you're already deploying to systemd-managed Linux hosts and find yourself writing ad-hoc 'wait for X before running Y' logic inside a cron script, that's usually the signal to switch.

When you actually need a workflow engine

Tools like Airflow, Dagster, or Temporal solve a different problem than cron entirely: a graph of tasks with dependencies between them, automatic retries with backoff, and a UI showing exactly which step of a multi-stage pipeline failed and why. If your 'cron job' is actually five scripts that have to run in a specific order, each one needing to know whether the previous one succeeded, you don't have a scheduling problem anymore — you have a workflow orchestration problem, and no amount of clever chaining makes cron the right tool for that.

The common failure mode here is building an increasingly fragile pile of shell scripts that check for lock files and previous-step output, essentially hand-rolling a worse version of what a workflow engine already does well. If that pattern sounds familiar, it's usually cheaper in the long run to adopt the real tool than to keep patching the homemade one.

When a cloud scheduler beats both

If the job's job is really 'make an HTTP request on a schedule' — hit an API, trigger a serverless function, refresh a cache via a webhook — a managed cloud scheduler (AWS EventBridge Scheduler, Google Cloud Scheduler, or a platform-specific one like Vercel Cron) usually beats self-hosted cron outright: no server to keep alive just to run cron, built-in retry policies, and centralized logs without any setup. The tradeoff is vendor lock-in and, on some platforms, real limits on frequency unless you're on a paid tier.

A rough decision framework

Stick with plain cron if the job is a single command, doesn't depend on other jobs' outcomes, and a missed run isn't a crisis (or you've added a heartbeat check). Move to systemd timers if you're already on systemd-managed servers and need dependency ordering or built-in logging. Move to a workflow engine once you have more than two or three steps that depend on each other's success. Move to a cloud scheduler when there's no server you actually want to keep running just to host a crontab.

Key Takeaways

  • Cron remains the right default for simple, independent, fixed-time tasks — don't add infrastructure you don't need.
  • systemd timers are worth it specifically for dependency ordering and built-in structured logging, not as a blanket upgrade.
  • If you're chaining scripts with lock files to fake step-dependencies, that's the signal you actually need a workflow engine.
  • Cloud schedulers remove the 'keep a server alive just for cron' cost, at the price of vendor lock-in and sometimes frequency limits on free tiers.

Frequently Asked Questions

Is cron obsolete?
No — for single, independent, fixed-time tasks it remains the simplest tool that reliably works, and switching away from it for jobs that don't need more is pure added complexity.
What's the clearest sign I've outgrown cron?
When you find yourself writing shell logic to check whether a previous job succeeded before running the next one — that's dependency management, which is exactly what workflow engines handle natively and cron doesn't handle at all.
Do systemd timers replace the need for a workflow engine?
No — timers solve single-job dependency ordering and logging on one machine. They don't provide retries with backoff, a UI showing pipeline state, or coordination across multiple jobs the way a real workflow engine does.