CronHub

Build cron expressions visually — with a live schedule preview.

Cron vs Systemd Timers: Which Should You Use?

Here's the short verdict on cron vs systemd timers: use cron for simple, personal, or portable jobs; use systemd timers when you need logging, missed-run catch-up, or dependencies on other services. Cron wins on simplicity — one line and you're done. Systemd timers win on operational robustness — at the cost of writing two unit files.

Both schedulers run scheduled tasks on Linux reliably. The right choice depends on what happens around the job: what you do when it fails, what happens if the machine was off, and how much machinery you're willing to maintain. Let's compare them properly.

Quick Comparison Table

FeatureCronSystemd timers
SetupOne crontab lineTwo files (.service + .timer)
LoggingEmail or manual redirectionAutomatic, via journald
Missed runs (machine off)Skipped*Caught up with Persistent=true
DependenciesNoneFull systemd ordering (After=, Requires=)
Randomized delayLimited supportRandomizedDelaySec= built in
Sub-minute precisionNo (1-minute floor)Yes (OnUnitActiveSec=30s)
Resource controlNoCPU/memory limits via unit options
PortabilityEverywhere Unix-likeSystemd distros only
Learning curveMinutesHours

*Anacron covers daily/weekly/monthly catch-up on many distros, but not arbitrary schedules.

The Same Job, Both Ways

Seeing both side by side makes the trade-off concrete. Say we want a backup at 2:30 a.m. daily.

Cron — one line via crontab -e:

30 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

Systemd — two files. First /etc/systemd/system/backup.service:

[Unit]
Description=Nightly backup

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh

Then /etc/systemd/system/backup.timer:

[Unit]
Description=Run backup nightly at 2:30

[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true

[Install]
WantedBy=timers.target

Enable and start it:

sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers backup.timer

More ceremony, clearly. What do you get for it?

Where Systemd Timers Pull Ahead

Logging comes free

Every run's output lands in the journal automatically:

journalctl -u backup.service --since yesterday

With cron, you either redirect output yourself on every line or dig through local mail. For debugging a 3 a.m. failure, journalctl is a genuine quality-of-life upgrade.

Missed runs get caught up

Persistent=true means: if the machine was off at 2:30, run the job at next boot. Cron simply skips missed runs — if your laptop sleeps through the schedule, the backup never happens.

Dependencies and ordering

A timer's service is a full systemd unit. Need the backup to wait for the network, or never run while another service is active? After=network-online.target handles what cron can't express at all.

Spreading the load

RandomizedDelaySec=600 staggers a fleet of servers so a thousand machines don't hammer the backup target at exactly 02:30:00. On its own, vanilla cron has no native equivalent.

Where Cron Still Wins

OnCalendar Syntax at a Glance

Systemd's time format differs from cron's five fields. The shape is DayOfWeek Year-Month-Day Hour:Minute:Second:

OnCalendar=daily                    # midnight every day
OnCalendar=*-*-* 02:30:00           # every day at 2:30 a.m.
OnCalendar=Mon *-*-* 09:00:00       # Mondays at 9 a.m.
OnCalendar=*:0/15                   # every 15 minutes

Test any expression before deploying:

systemd-analyze calendar "Mon *-*-* 09:00:00"

The command prints the normalized form and the next elapse time, so you can confirm the schedule before the timer ever fires — systemd's answer to crontab.guru.

Migrating a Cron Job to a Timer

The translation is mechanical once you've done it twice:

  1. Move the command into a .service file with Type=oneshot.
  2. Convert the five cron fields to an OnCalendar= expression (verify with systemd-analyze calendar).
  3. Add Persistent=true if missed runs should catch up.
  4. daemon-reload, then enable --now the timer.
  5. Delete the crontab line only after systemctl list-timers shows a sensible next-run time and one run has appeared in journalctl -u yourjob.service.

Keep both scheduled in parallel for a day only if the job is idempotent — otherwise you'll run it twice.

Common Mistakes

  1. Forgetting Persistent=true and then wondering why a laptop's timer never fires — the machine is asleep at the scheduled moment.
  2. Enabling the service instead of the timer. Run systemctl enable backup.timer, not backup.service. Enabling the service can run the job at every boot.
  3. Skipping daemon-reload after editing unit files, so changes silently don't apply.
  4. Rewriting every cron job as a timer on principle. A five-line crontab that has worked for years does not need migrating.
  5. Assuming cron logs somewhere useful. It logs that jobs started (syslog), not what they printed. That's why redirection matters.

So Which Should You Choose?

Choose cron when:

Choose systemd timers when:

Many production systems sensibly use both: cron for small housekeeping, timers for anything business-critical.

Conclusion

The cron vs systemd timers question has a practical answer: cron for convenience and portability, systemd timers for observability and robustness. Neither is obsolete, and the skills transfer — a schedule is a schedule, whether it's written 30 2 * * * or OnCalendar=*-*-* 02:30:00.

If you're staying with cron, our cron syntax guide and crontab examples will make you fast. If you're going the timer route, pair it with proper monitoring so failures never go unnoticed either way.

Frequently Asked Questions

Are systemd timers better than cron?

They're more capable — built-in logging, missed-run catch-up, and service dependencies — but not universally better. Cron is simpler, more portable, and entirely sufficient for basic scheduled tasks on Linux.

Do systemd timers replace cron?

On systemd-based distros they can, and some minimal server setups ship without cron installed. But cron remains standard nearly everywhere, and the two coexist without conflict on the same machine.

How do I see all active systemd timers?

Run systemctl list-timers. It shows each timer's next scheduled trigger, the time remaining, the last run, and the service unit it activates.

Can a systemd timer run more often than once a minute?

Yes. Unlike cron's one-minute floor, timers support second-level scheduling — for example OnUnitActiveSec=30s re-runs a job 30 seconds after its last activation.

What happens to a cron job if the server is off at the scheduled time?

Standard cron skips it entirely; there's no catch-up. Systemd timers with Persistent=true run the missed job as soon as the machine is back up — a key difference for laptops and intermittently-running machines.

Need the expression itself? Build and test any cron schedule in our free visual generator — with live upcoming-run previews in Unix and Quartz formats.

Related guides

References