Automation Layer
Automation and Scheduling in Three Tiers
Every scheduled job runs in one of three places, and each place fails in its own way. Customer work runs on server cron or inside the request itself, never on a laptop that might be closed.
- Year 1Website
- Year 2Map Listings
- Year 3Booking Tool
- Year 4Front Desk
- Year 5Payments
- Year 6Reports
Same six pieces.
Ten layers, already running.
The Short Version
- App-open tasks only run while the app is open.
- Windows Task Scheduler survives a closed app but not a powered-off machine.
- Server cron is the only tier that does not care about the laptop.
- Anything a customer waits on happens inside the request, not on a timer.
| Tier 1 | Tasks in an open app |
|---|---|
| Tier 2 | Windows Task Scheduler |
| Tier 3 | Server cron |
| Customer work | Server cron or inside the request |
| Cron clock | UTC |
| Alarm | On the outcome, not the run |
- Customer Is WaitingRun inside the request
- Customer-Facing, TimedServer cron
- Internal, Laptop OnTask Scheduler
- Only While WatchingApp-open tasks
- Every TierAlarm on outcome
A Schedule Is Not a Promise
People treat a scheduled job like a promise. Send the reminder at 9. Post the report on Monday. Then the laptop was asleep, or the server was busy, and the job ran late or not at all. Nobody finds out until a customer asks where their message went.
A schedule is a request that something run around a time. Cron can run late. A machine can be off. So we sort every job by one question: what happens if this does not run on time? The answer tells us which tier it belongs in.
Tier One: Tasks in an Open App
Some tools can run a task on a timer while the app is open. That is handy for work you are watching anyway, like a scan you want every hour during the day.
The catch is plain. Close the app and the timer stops. Nothing warns you. So this tier is only for work where a skipped run costs nothing. If a missed run would matter to anyone but you, it does not belong here.
Tier Two: Windows Task Scheduler
Task Scheduler runs a job even when no app is open. It survives a reboot. It does not survive a machine that is off, asleep with no wake timer, or out of battery.
Its defaults are also wrong for unattended work. Out of the box, a task may refuse to start on battery, stop when the charger is pulled, and skip a missed run for good. A one-time task is worse. If the machine is off at that minute, the task never runs, and nothing tells you. We set every task on purpose.
$action = New-ScheduledTaskAction -Execute "py" -Argument "nightly.py" `
-WorkingDirectory $PSScriptRoot
$trigger = New-ScheduledTaskTrigger -Daily -At 6am
$settings = New-ScheduledTaskSettingsSet `
-AllowStartIfOnBatteries `
-DontStopIfGoingOnBatteries `
-StartWhenAvailable `
-ExecutionTimeLimit (New-TimeSpan -Hours 1)
Register-ScheduledTask -TaskName "Nightly job" -Action $action `
-Trigger $trigger -Settings $settings-StartWhenAvailable is the one that matters most. It runs a missed job as soon as the machine is back. Even so, this tier is for our own work, like a data pull or a build. It is never for anything a customer is waiting on.
Tier Three: Server Cron
Server cron runs on a machine we do not carry around. It does not care if the laptop is closed, on a plane or in a lake. That makes it the only tier for customer-facing timed work. Review requests. Estimate nudges. Weekly reports.
We run most of these as Cloudflare Worker cron triggers. The schedule lives in the Worker config, and the Worker has a handler for it.
export default {
async scheduled(controller, env, ctx) {
ctx.waitUntil(sendWeeklyReports(env));
},
};
async function sendWeeklyReports(env) {
// Build each report, send it, and record that it went out.
}One thing to know. Cron runs on UTC. A job set for a fixed hour will shift by an hour when your local clock changes for daylight saving. For anything tied to local time, we run often and check the local hour inside the job, instead of trusting a fixed time.
If a Customer Is Waiting, Do It Now
This is the rule that ties the rest together. If a customer is waiting on something, it does not go on a timer at all. It happens inside the request.
Say a customer fills out a quote form. The confirmation text should go while they are still on the page. Not in the next cron run. Not in five minutes. If the send fails, the page can say so and they can try again. A timer that fails at 3am tells nobody.
Timers are for work that can wait. Everything else runs the moment it is asked for.
The same goes for a follow up that must go at a set time, like a reminder the day before a booking. We still save it the moment the booking is made, with the time it is due. Cron then only has to find what is due and send it. If cron runs late, the reminder is late, not lost, and the next run picks it up.
What It Saves the Owner
You stop finding out from a customer that a reminder never went. You stop wondering if a job ran while your laptop was closed. Every job sits in a tier that fits the cost of it failing. The ones that touch your customers run on servers that do not sleep.
This is how our daily news desk publishes on time and how our follow ups go out.
What We Learned the Hard Way
Alarm on the outcome, not on whether the job ran. A job can run on time and fail every time. A monitor that checks it started will stay green. So we check the thing the job was for. Did the report arrive? Did the text send? That question is true or false no matter what broke.
Derive state, do not schedule it. Two jobs that flip a setting at dawn and dusk will one day miss a flip, and the setting stays wrong all day. One job that runs often and fixes the setting when it is wrong heals itself on the next run.
Know where each job runs. A job that lives on one person's laptop is a job that stops on vacation. We keep a list of every job, its tier and what it is for.
For the full guide, read scheduled jobs that actually run. To start at the top of the stack again, go back to edge hosting.
Questions People Ask
Will my reminders still go out if your computer is off?
Yes. Anything that reaches your customers runs on a server, not on a laptop. It does not care if any computer in the office is on.
What if a scheduled message fails to send?
Our alarms check whether the message actually went out, not whether the job started. If customers are not getting it, we hear about it.
Why does my confirmation text arrive right away instead of in a batch?
Because you are waiting on it. Anything a customer waits for runs the moment they ask, not on a timer.
Do my messages shift when the clocks change?
No. Jobs tied to local time check your local hour when they run, so daylight saving does not move them.
We sell time
Get Years of Building Switched On in Hours
A thirty minute call. A written price. Nothing built until you say yes.