A scheduled job that does nothing still looks green
engineering3 min read
Builder · Applied AI

A scheduled job that does nothing still looks green

A cron that crashes pages you. A cron that quietly stops firing, or fires and does nothing, says nothing at all, and silence looks exactly like success. So I built a heartbeat dashboard for silent failures. The first read found eleven jobs failing without a sound.

A cron job that crashes will page you. A cron job that quietly stops firing, or fires on schedule and does nothing, will not say a word, and silence is the one failure that looks exactly like success. Every green checkmark in my scheduler was telling me the job ran. None of them were telling me the job worked. So I built a dashboard whose only purpose is to notice that difference, and the first time it ran it found eleven jobs that had been failing without a sound.

The failure mode nobody alerts on

Alerting is built for errors: something threw, something returned non-zero, something timed out. The jobs that hurt me were doing none of that. A queue drainer that pulled zero items because the queue was mis-keyed and always empty. A notifier that exited clean after sending nothing. A health check that dutifully probed a URL that no longer existed. Each one was green. Each one was also completely inert, and the greenness was actively lying about it.

A catalog the workflows cannot drift from

The first piece is a catalog: every scheduled job, what it is, and how often it should fire. The obvious risk is that the catalog drifts from reality the moment someone adds a cron and forgets to list it. So the catalog is not documentation, it is a test. A check compares the catalog against the actual workflow files and fails if a job lives in one but not the other. You cannot add a scheduled job without the dashboard learning it should have run, because the suite goes red until you do. The invariant is encoded, not remembered.

js
// The gate, paraphrased: the catalog and the crons must match exactly.
const actual = scheduledWorkflowFiles();   // .github/workflows/*.yml
const claimed = catalogJobs();             // the burn catalog
expect({
  missing: actual.filter((f) => !claimed.includes(f)),
  phantom: claimed.filter((f) => !actual.includes(f)),
}).toEqual({ missing: [], phantom: [] });
// Add a cron, add a catalog row, or the build is red. No memory required.

Fired, skipped, or silent

With a trustworthy list of what should run, a probe classifies what actually happened in each job's window. Fired means it ran and did work. Skipped means it ran and correctly had nothing to do, which is fine. Silent means it did not run when it should have, or ran and produced nothing where nothing is the wrong answer. That third bucket is the whole point. It is the state no error-based alert will ever show you, and it is the one the dashboard paints red.

11jobs the first read caught firing green and doing nothing
agent-jobs-drainLIVE
telegram-cronLIVE
site-healthLIVE
grove-tickLIVE
seed-contentLIVE
firedsilent (green, no work)skipped
Each job as a heartbeat across its recent windows. The red runs are silent failures: green in CI, doing nothing in production, then healing after the fix.

The first read

Turning it on was uncomfortable in the good way. Eleven jobs came up silent. The queue drainer had been writing its key in the wrong case long enough that the queue it fed had never once filled. The notifier had been exiting clean while sending nothing, because a base URL it needed was unset in the scheduler. The health check had been probing a path a rename removed. None of these had ever thrown. All of them had been green for weeks. I fixed several that afternoon, and each fix was small; the hard part was never the repair, it was seeing the failure at all.

Spend on the same pane

While I was there I put month-to-date model spend against its ceiling on the same screen, because it is the same class of question. A budget that silently runs past its limit is a silent failure with a bill attached. One dashboard now answers both did every job that should have fired actually do something, and are we under the money line, which are the two things about this system I most want to be unable to not-know.

Where it stops

The honest limits. The reader is fail-soft and reports only booleans and timestamps, never a job's contents, and the whole thing is admin-only. It tells me a job went silent; it does not diagnose why. And it can only watch jobs the catalog knows about, which is exactly why the drift test, not the dashboard, is the load-bearing part. A pretty dashboard over a catalog that silently missed half the crons would just be a nicer way to be wrong. The test is what makes the green mean something.

Experience it yourselfSee the burn dashboard
ShareXLinkedInHacker NewsEmail

Get the next one

An occasional note when something genuinely new ships here — essays, free tools, projects. No schedule, no filler, easy out.

Need something like this built?

I design and ship AI tools, full-stack apps, and data pipelines — end to end, to production. Tell me the problem in a sentence; I'll give you an honest read on fit within a day.

Work with me →