Cronicle: The Distributed Cron Scheduler That Remembers Lost Time
A deep look at the cursor-based scheduler, UDP cluster discovery, and storage-agnostic design that make Cronicle feel simple on the surface and unusually durable underneath.
- Cronicle’s most distinctive move is treating missed schedule windows as recoverable state, not discarded history.
- Its cluster model stays intentionally lightweight, using UDP discovery and deterministic failover instead of a heavyweight consensus stack.
- The project’s custom Pixl-based engine and storage abstraction keep the system coherent across local disk and larger backends.
- Cronicle succeeds by staying narrow: it solves distributed cron well enough to feel finished, not endlessly expandable.
Cronicle looks like a polished web UI for cron. That undersells it. The real idea is more interesting: it behaves like a scheduler with memory, so downtime becomes a gap to replay rather than a failure to ignore.
That design choice changes the whole product. Instead of asking operators to trust a fragile clock tick, Cronicle tracks where it last checked, walks forward through missed intervals, and only then returns to normal cadence. The result is a system that treats time as durable state.
The scheduler that refuses to forget
Why catch-up matters more than it sounds
I built Cronicle to scratch my own itch. At work, we had a massive number of cron jobs spread across dozens of servers, and it was a nightmare to manage. We needed a central place to schedule, monitor, and debug these jobs, and nothing out there really fit the bill. So, I decided to build it.
That quote gets at the operator pain Cronicle is built around. A missed hour is not a cosmetic issue. It can mean delayed ETL, stale reports, skipped backups, or a job that silently never happened.
| Scenario | Traditional cron | Cronicle |
|---|---|---|
| Server is down during a run window | The run is missed unless you bolt on extra logic. | The scheduler advances through missed slots after recovery. |
| Visibility across a fleet | Mostly local and fragmented. | Centralized web UI with real-time job status. |
| Operational recovery | Manual inspection and ad hoc fixes. | Catch-up behavior is built into the scheduler model. |
A cluster that forms itself
Cronicle’s distributed story is unusually pragmatic. It does not try to solve consensus in the abstract. It uses UDP broadcast discovery to find nearby servers, then applies a deterministic promotion path so the cluster can recover without a heavyweight coordination system.
| Coordination choice | What it buys | What it avoids |
|---|---|---|
| UDP discovery | Low-friction server awareness on a LAN or VLAN. | A central registry just to form a cluster. |
| Deterministic failover | A clear path from master loss to backup promotion. | A full consensus service for every scheduling decision. |
| Nearby-server model | Simple cluster formation. | Turning a cron system into a distributed systems research project. |
The engine room behind the web UI
Under the hood, Cronicle is a Pixl-stack Node.js application. `lib/main.js` boots the server, `lib/engine.js` acts as the core orchestrator, and mixins pull in API, scheduling, and discovery behavior. It is a monolithic engine, but not a sloppy one. The architecture is deliberate enough to keep the app internally consistent.
// Conceptual shape of the Cronicle engine
const Engine = require('./engine');
server.on('tick', function() {
engine.checkSchedules();
engine.updateClusterState();
engine.launchDueJobs();
});
// Scheduler state keeps cursors so missed time can be replayed
this.state.cursors[eventId] = lastCheckedTime;
The storage layer follows the same philosophy. By leaning on `pixl-server-storage`, Cronicle can back onto local disk, S3, or Couchbase without rewriting the core scheduling logic. That is less glamorous than a consensus algorithm, but it is what makes the project portable.
Jobs are not events
One reason Cronicle stays manageable is that it keeps a tight distinction between an event definition and a job instance. The event describes what should happen. The job is the actual execution, with its own lifecycle, logs, and resource checks.
| Concept | What it represents | Why it matters |
|---|---|---|
| Event | A reusable schedule definition. | Keeps intent separate from execution history. |
| Job | A single launched run. | Makes monitoring and retry behavior concrete. |
| Category and global limits | Backpressure across the system. | Prevents one schedule from overwhelming the fleet. |
That separation also explains Cronicle’s resource controls. Limits can apply at the event, category, and global level, so the scheduler can multiplex work across servers without letting one hot path crowd out everything else.
The case for a finished scheduler
Cronicle reads like software that reached its design center and stopped. It is not trying to become a general workflow engine or a container orchestrator. That restraint is part of the product value.
| Tool | Best for | Operational shape |
|---|---|---|
| Cronicle | Distributed cron and scheduled jobs. | Focused, operator-friendly, relatively light. |
| Airflow | Complex data pipelines and DAGs. | Heavier, more expressive, more moving parts. |
| Rundeck | Runbook automation and enterprise ops workflows. | Broader scope, more platform-like. |
| Nomad | General workload orchestration. | Useful when scheduling is only one concern. |
| Jenkins | CI and ad hoc job automation. | Flexible, but cron-like use can feel bolted on. |
| Dkron | Distributed cron replacement. | Closest in intent, usually smaller in surface area. |
That is why Cronicle still feels distinct. It occupies the narrow but valuable space between a bare crontab entry and a full orchestration platform. For the right team, that is exactly the sweet spot.