Behind the Build · No. 18

Did the scheduled job run, or only fire?

A scheduled job can start on time and leave nothing behind. Here is the one quick check per job that separates fired from done.

An hourglass resting on a blank checklist, with a few autumn leaves drifting around it.

We once chased a quiet scheduled job through power settings and a busy scheduler, and both theories turned out to be wrong. If a backup, a report or a post runs on a timer for your business, this is your Halloween ghost story.

To check that a scheduled backup ran, look at what it produced, not at whether it started. Give each job one simple test: a file, row or count that is new since the last run and not empty.

Example job report

Nightly backup

  • Started on schedule Pass
  • Ended without an error Pass
  • Wrote a file above the floor Fail

1 failed

Notice that the two passing lines are about starting and ending, and only the failing one is about the output. This is an example.

Fired is not the same as done

A schedule is a promise to start something, and it says nothing about what the thing did after it started. A fired job and a finished job are different events. The green mark you see is about starting, and sometimes about exiting without an error. Neither one tells you whether the output has anything in it.

Think of a delivery that was scheduled for noon. The truck leaving the depot at noon tells you the plan began. It does not tell you a parcel is on your doorstep. A scheduler is the depot, and your output is the doorstep. Only one of them matters to you.

This is why a green dashboard feels so convincing. It answers a question you did not quite ask, which is whether the plan started, and it leaves the real question unanswered.

Our opinion, stated plainly so you can borrow it: judge a schedule by what it left behind, never by the fact that it fired.

How a quiet job usually plays out:

  1. At first

    The starts look fine

    A scheduler shows the jobs beginning on time. Nothing is red, so nobody looks closer.

  2. Meanwhile

    The shelves stay empty

    The output folder or table stays empty while the schedule keeps looking healthy.

  3. The lesson

    Judge by output

    A job is done when its output exists and is newer than the last run.

That is why one check on the output beats a clever alarm on every cause.

What we ruled out first

When jobs go quiet, the first theories are the ordinary ones. Power management was ruled out. Scheduler starvation, where the machine is too busy to start a job on time, was ruled out. So was the idea that the jobs never fired. In our view, a look at the output is the faster first move, and chasing causes comes second.

Causes multiply and outputs do not. A quiet job might have many possible reasons, and you can lose days sorting them. That is also why a long list of theories feels like progress: each one can be tested, and each one eats an afternoon. The output only ever says yes or no: the thing you needed is there and new, or it is not. Start with that answer, then go hunting for the reason.

The trap is that no alert feels like no problem, so nobody looks. We wrote about the same trap with tracking in how to check Google Analytics is working, and about a cousin of it in why permanent analytics belongs in the code.

Judged by the schedule

  • The job appears on the list at its start time
  • No error message, so no worry
  • Done means it started

Judged by the output

  • A new file or row exists
  • It is newer than the last run
  • It is not empty
  • Done means it left something behind

One simple check per job

For each job, write down what it should leave behind, where it should be, and how new it should be. Then add a floor: how small is too small. A backup that wrote zero bytes passes every test except the one that matters.

Keep the check dull. It should read one thing, compare it to one rule, and answer yes or no. It should be plain enough that a stranger could run it. The example job report above shows it: started, finished, and the third line fails the moment you read it.

A quick example for a daily backup. The check opens the backup folder, finds the newest file, and asks two things: is it from today's run, and is it above the floor? Two yes answers mean done. Anything else sends a message to a person.

A floor is easier to set than it sounds. Look at a few normal outputs, note the smallest one that was still fine, and set the floor just under it. The goal is to catch the empty file and the half-written file.

Newer than the last run depends on the rhythm. For a daily job, the output should be from the latest daily run. For a weekly job, it should be from the latest weekly run, since an older file may still be sitting there. Write the rhythm next to the job, so the check knows how old is too old.

Notice that the check changes with the job, but each one asks for something you can open and look at.
JobWhere the output livesHow new it must be
BackupA file in the backup folderWritten since the last scheduled run
ReportA sent message or a saved fileDated for the latest run
Scheduled postA live page on your sitePublic at its scheduled time

If a job can log its own output count, a plain local file is enough. SQLite is one simple choice for a small local file that a job can write its own count into. If the job publishes something public, check the public side too. Search Console is one place to see whether what a scheduled publish put live has reached Google. Both are suggestions from us.

If the public side of this, a scheduled post that should be live and findable, is where you get stuck, our technical SEO service page explains how we work.

Decide who sees a failure and where, because a failed check nobody reads is just another silent job. And in our opinion, do not run the check from the place the job writes to. If that place goes missing, the check goes quiet with it. Name an owner, too. A check with no name beside it is a check that nobody feels responsible for, and it will rot.

What goes quiet, and how to test it
  • Backup job What breaks Starts, then writes an empty file
    Backup job How to check Check the file is larger than your floor and newer than the last run
  • Report job What breaks Runs, but nothing arrives
    Report job How to check Look for the sent message with today's time on it
  • Scheduled post What breaks Fires, but nothing goes live
    Scheduled post How to check Open the page, then look for it in Search Console
  • Setup stage What breaks Stops before the first real step
    Setup stage How to check Look for a log line from the first real step, not the start line

Tap a card to flip it. Each failure looks like success until you open the output.

Which job would you miss first?

Pick the job that would hurt most if it stopped tonight. It might be a backup, the report your vendor sends you, or the post that goes out on a timer. Write its one check today, and put the answer where a person will see it.

Optymize your schedule by giving that job its own output check first, then work down the list.

We try to hold our own changes to the same standard. On one recent set of edits, we had a script confirm that each anchor matched exactly once before anything was written, so nothing landed by line number or a near match. Say what you expect, then check that you got it. A schedule deserves the same treatment.

If you want the longer story on silent failures in a paid campaign, we wrote about that in the three pause layers behind a campaign that was not serving.

Any gap longer than one missed run is hope, not monitoring. If your most important job went quiet tonight, how many days would pass before anyone noticed?

Do this week

Ready to ship

Talk to Offer before you decide anything.

You'll talk with Offer, not a sales rep. A short call, no pitch deck.

Talk to Offer

This post was drafted with AI tools from our own project records, anonymized, and checked by us before it published. Read our editorial standards.

Related Articles

Want to talk through your marketing?

Tell us where things stand and we'll tell you plainly what we'd do next.