Distributed Cron Jobs
Regular cron runs on one server. What happens when you have 10 servers? Each runs the job 10 times. That's a problem. The Problem Single server cron: ✅ Job runs once at 2am 10-server fleet: ❌ Job runs 10 times at 2am — duplicate emails, double charges! Solutions 1. Dedicated Scheduler Node One designated machine runs all cron jobs ✅ Simple ❌ Single point of failure — if this node dies, no cron…
Cron jobs are scheduled tasks that run on a single server, but what happens when a system grows to 10 or more servers? Each server would attempt to run the same job ten times, leading to duplicate emails, double charges, and other issues.
The first solution is to designate one machine as a dedicated scheduler node. This node runs all cron jobs, ensuring only one instance executes at a time. However, this approach creates a single point of failure - if the scheduler node goes down, no jobs run.
A second option is to implement leader election using tools like etcd or ZooKeeper. The cluster elects a leader, and only the leader runs the cron jobs. If the leader fails, a new leader is automatically elected, and the cron resumes. While this eliminates the single point of failure, it introduces complexity in managing leader election.
Another approach involves using distributed locks before executing the job. The code attempts to acquire a lock in Redis with a 5-minute TTL (time-to-live). If the lock can't be acquired, the function returns early, avoiding duplicate execution. After the job runs, the lock is deleted. While this method works with existing Redis, the lock expiry must match the job duration, or an additional heartbeat mechanism should be added.
Dedicated scheduling services provide an alternative to traditional cron jobs. AWS EventBridge Scheduler allows scheduling without servers, while Temporal.io offers workflow orchestration with built-in scheduling capabilities. Airflow utilizes Directed Acyclic Graphs (DAGs) to define and manage job schedules. Additionally, Ruby's Sidekiq-Cron and Node.js's Bull libraries provide cron-like functionality within each application.
For critical jobs like billing or email notifications, ensuring exactly-once execution is crucial. Implement idempotency keys within the job itself to prevent duplicate processing. Record the execution date in the database before running the job; if the row already exists, skip the execution. Use a distributed lock with heartbeat to detect and handle failures.
Implement observability tools such as Healthchecks.io to monitor cron jobs - if a job fails to run (misses its heartbeat), alert the team, track job duration for anomalies, and log job results (success or failure, records processed).
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.