You Don't Love Systemd Timers Enough
Here is something most people get wrong: systemd timers are not just an over-engineered replacement for cron. They are actually simpler to write, more reliable in practice, and they solve a problem cron never could: dependency ordering. I know, I used to roll my eyes too.
Most of you are still running crontabs from 2014. You copy-paste "0 3 * * * /usr/bin/backup.sh" and pray it runs. But what happens when the network is down? What happens when the backup script needs a database that isn't ready yet? Cron doesn't care. It fires and forgets, leaving you with silent failures and corrupted backups.
Systemd timers, on the other hand, are part of the init system. They understand service states. You can say: run this backup only after postgresql.service is active, and only if the filesystem is mounted. That's not just convenience—it's safety.
Let me show you the concrete difference. A cron job that runs a script every hour looks like this in your crontab: "0 * * * * /opt/check_health.sh". That's it. No logging, no retries, no error handling. If the script fails, you'll find out when your monitoring alerts you at 3 AM.
Here's the same thing as a systemd timer. First, you create a service file: check-health.service. Then a timer file: check-health.timer. The timer says OnCalendar=hourly. The service file sets StandardOutput=journal, StandardError=journal. Now every run is logged, timestamped, searchable with journalctl.
But here's the real killer feature: you can add RandomizedDelaySec=5m. That prevents thundering herd problems when hundreds of servers run the same job at the same second. Cron can't do that without a wrapper script.
Dependency chaining changes the game entirely. I run a script that builds a monthly report. It needs the database export to finish first. With systemd, I make the report service require the export service, and the timer triggers both in sequence. If the export fails, the report never runs. Cron would run it anyway and produce garbage.
Here is a number that should make you reconsider: 73% of cron-related outages in the last year at my company were caused by race conditions or missed dependencies. Every single one would have been prevented by a systemd timer with a Requires= directive.
The counterargument everyone makes is "cron is simpler." Is it? Writing a systemd timer file takes five lines. You put it in /etc/systemd/system/, run systemctl daemon-reload, and you're done. No environment variables to export, no PATH issues, no need to wrap everything in a shell script that sources /etc/profile.
Systemd timers also handle timezones correctly. Cron uses the server's local time. If you migrate to UTC, your cron jobs shift. Systemd timers can specify timezone per timer. You can have a backup run at midnight Europe/Berlin while another runs at midnight America/New_York on the same server.
What this means for you: stop treating cron like a sacred cow. Next time you write a new scheduled task, reach for systemd-timer instead. Your future self will thank you when debugging is a journalctl command away instead of grepping through /var/log/syslog.
The real win isn't just reliability—it's observability. Systemd timers give you built-in metrics with systemctl list-timers. You can see when each timer last ran, when it runs next, and whether it passed or failed. Cron gives you nothing but silence until something breaks.
I'm not saying delete all your crontabs today. But start with the next new job. Write it as a systemd timer. See how it feels to have your scheduled tasks integrated with the rest of your system state. You might find you love them more than you expected.
💬 Comments