Scheduled Job Monitoring: A Four-Layer Health Checklist
Builderlog currently has five scheduled jobs attached to it: publishing, queue upkeep, statistics, Threads distribution, and prompt monitoring. Seeing all five in the scheduler is reassuring. It is not proof that any of them did useful work.
The status screen is only the first check
A scheduled job can be loaded while its last run failed, while its input queue is empty, or while the generated page never reached the public site. Those states look similar if the only question is “is the job present?”
The audit therefore starts with the scheduler but never ends there. For each job, I need to connect four pieces of evidence:
- the job is loaded with the intended schedule;
- the newest log records a completed action rather than an old success;
- the expected file or queue state changed;
- the public URL returns the result a reader should see.
Loaded is configuration. Healthy is a verified output.
The evidence chain for the publishing job
The main Builderlog job runs on weekdays. Its log records generation, the bilingual content files, the site build, deployment, and the dev.to cross-post. Each line is useful, but the public page is the final check.
For the latest run in this audit, the numbered post file existed, the deployment log reported success, and the corresponding Builderlog page returned HTTP 200. The queue then contained five unused topics. That combination proves more than a green scheduler row: one topic was consumed, one public artifact appeared, and work remains for the next run.
If the deployment log said success but the numbered URL returned 404, the job would still be unhealthy. If the page existed but the queue had not advanced, the next run could repeat the same topic. Both failures have happened often enough in automation systems that they deserve separate checks.
Why the other four jobs need different proof
The queue-maintenance job should be judged by whether it leaves genuinely unused topics, not by whether it rewrites a file. The statistics job should be judged by a fresh reporting date, not by an old output file. The Threads job should be judged by a recorded distribution result. The prompt monitor should be judged by whether its source data and timestamp changed.
These are different contracts. A single “process exited with code zero” check cannot prove all of them.
This is the part that makes automation maintenance less glamorous than automation building. Every job needs a precise answer to two questions: what state is it supposed to change, and what external result proves that change mattered?
The small audit table I now use
| Layer | Evidence | Failure it catches |
|---|---|---|
| Schedule | Loaded job and intended weekday/time | Missing or shifted trigger |
| Execution | Newest run log and exit state | Crash, empty run, stale success |
| State | Queue, file, or metrics timestamp changed | No-op and duplicate consumption |
| Public result | Expected URL and content are reachable | Build or deployment mismatch |
The order matters. Public output is checked last because it is the closest thing to the reader’s experience. Internal success without that last check is only a plausible story.
What this changes about future automation
New jobs do not get added to Builderlog with only a schedule and a script. They also need an output contract, a current log, and a public or state-level verification step. If one of those is missing, the job is not finished.
That rule also prevents a common maintenance trap: an old green log can make a dead pipeline look healthy for days. Checking the newest timestamp and the newest artifact keeps “success,” “skipped,” and “failed” as three different states.
The useful automation is not the one that runs. It is the one whose result can be proven.
Builderlog has five scheduled jobs, but the scheduler is only the first layer of evidence. A healthy run needs a fresh log, an expected state change, and a verified public result.