[ OK ]Initializing kernel...
~/im/blog
Hire Me

Let's Talk

Interested in working together or have a question? I'm always open to discussing new projects.

Get in touch

Connect

Find me on social media and professional networks.

Privacy PolicyTerms of Conditions
© 2026 Irfan MiralDeveloped byirfanMiral.com
HomeAbout/ResumeBlogContact
2026-03-05• 5 min read

Cron vs systemd Timers: When I Reach for Each

DevOps Linux Administration systemd Automation

Every time this comes up, someone makes the case that systemd timers should replace cron entirely. They're not wrong about the capabilities, timers have better logging, can depend on other units, and survive a server being off when the job should have run. And yet I still write cron jobs regularly, because the choice isn't really about features. It's about who has to read this in a year, and how much ceremony the job actually deserves.

Where cron wins: small, simple, well-known

A cron job is one line. Anyone who has touched Linux in the last twenty years can read a crontab and understand it without documentation:

# /etc/cron.d/cleanup-tmp
0 3 * * * root find /tmp -type f -atime +7 -delete

For jobs like this, the systemd equivalent is two files, a .service and a .timer, plus an enable step, for a job that doesn't need any of the extra capability those files provide. The overhead isn't really about typing, it's about the next person who has to find this job during an incident. crontab -l or a quick look in /etc/cron.d/ is the first thing most Linux admins check. A timer that nobody knows to look for is a job that effectively doesn't exist until someone stumbles onto it.

My rule: if the job is a single command, doesn't need to react to failure, and a missed run wouldn't matter, it's cron.

Where systemd timers win: anything that needs to be trusted

The moment a scheduled job actually matters, backups, certificate renewals, anything where a silent failure becomes a 2am page, systemd timers earn their extra setup.

# /etc/systemd/system/backup.service
[Unit]
Description=Nightly database backup

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup nightly

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

[Install]
WantedBy=timers.target
systemctl enable --now backup.timer
journalctl -u backup.service

Three things here that cron doesn't give you for free. journalctl -u backup.service shows the full output and exit status of every run, no need to redirect to a log file and hope you remember to rotate it. Persistent=true means if the server was down at 2am, the job runs as soon as it's back up, rather than silently waiting a full day for the next scheduled time. And systemctl status backup.timer tells you exactly when the job last ran and when it'll run next, which for a cron job means reading the schedule and doing the math yourself.

The actual deciding question

When I'm setting up a new scheduled task, the question isn't "which is more modern." It's: if this job fails silently, how long before someone notices, and does that matter?

If the answer is "it doesn't really matter, and if it did, I'd notice some other way" (a tmp cleanup, a cache warm-up, a log rotation that's also covered by logrotate anyway), cron is plenty, and its simplicity is a feature, not a limitation. If the answer is "this is the only thing standing between us and data loss" or "a missed run here becomes a customer-facing problem," the extra two files and the proper logging that comes with a systemd timer are worth it every time.

Most servers I manage end up with both, a handful of cron one-liners for housekeeping, and a small number of systemd timers for the jobs that actually need to be trusted. That mix isn't a compromise, it's matching the tool's ceremony to the job's importance, and it means the systemd timers on a box are a short, meaningful list rather than noise to scroll past.

PreviousWhy Server Configs Belong in Git, Not in Your HeadNext VPS or Bare Metal: How I Actually Decide