Technical July 2026 11 min read

Cron vs Daemon vs launchd: How to Schedule Automation

Every automation needs to run on some schedule, or run all the time. There are three fundamentally different ways to make that happen, and picking the wrong one is why "automated" processes quietly stop working and nobody notices for weeks.

A bookkeeping client of ours had a script that pulled new invoices every morning at 6am. It ran on cron. One week the laptop it lived on didn't wake from sleep in time, cron never fired, and nobody found out until three weeks of invoices had piled up unprocessed. Nothing crashed. Nothing errored. The job just silently never ran, which is exactly the failure mode cron is built to produce if you don't plan around it.

That story isn't really about cron being bad. It's about picking the wrong tool for the job without knowing there were other options. There are three distinct ways to make a piece of automation run on a schedule or continuously in the background, and each one has a different failure mode, a different granularity, and a different amount of babysitting it needs. This post walks through all three in plain English, with a comparison table and a decision guide at the end.

The Three Ways to Run Something Automatically

Before getting into the details, here's the one-sentence version of each:

None of these is universally "better." They solve different problems. Understanding which one fits your situation is the difference between automation that quietly runs for years and automation that quietly stops running for weeks before anyone notices.

Cron: The Time-Based Scheduler

Cron has been running on Unix-like systems since the 1970s. It's a background process that wakes up once a minute, reads a list of scheduled jobs (the crontab), and for each job whose scheduled time matches right now, it launches the associated command. Then it goes back to sleep until the next minute.

A typical cron line looks like this:

Example crontab entry
0 6 * * * /usr/bin/python3 /home/user/pull_invoices.py

That reads as "at minute 0 of hour 6, every day, every month, every day of the week, run this script." It's compact, it's been battle-tested for five decades, and it's available on essentially every Linux server and every Mac out of the box.

Where cron is strong

Where cron falls apart

The core cron problem: it optimizes for "fire and forget," which is also its biggest liability. It will never tell you it stopped working. Something else in your stack has to watch it for that.

Daemons: The Always-On Worker

A daemon (the term comes from old Unix jargon, unrelated to anything supernatural) is a process that starts once and keeps running indefinitely, usually structured as a loop: check for work, do the work if there is any, wait a bit, repeat. It's the pattern behind most "listening" software, mail servers, message queue workers, chat bots, and monitoring agents.

The simplest possible daemon is a `while True` loop with a sleep in it:

Conceptual daemon loop (Python)
while True: check_for_new_orders() process_anything_found() sleep(5)

That process starts once, holds its state in memory the entire time it runs, and reacts within seconds of new work arriving instead of waiting for a clock to strike. Real daemons are usually more sophisticated, listening for events instead of polling on a timer, but the underlying idea is the same: it's alive continuously, not launched-and-exited on a schedule.

Where a daemon is strong

Where a daemon gets harder

launchd: macOS's Native Answer to Both

launchd is the process that macOS itself uses to start almost everything on the machine, from system services to the Dock. Apple designed it to replace both cron-style time scheduling and the traditional Unix daemon-management tools in one system, and it has been the default init system on macOS since 2005 (10.4 Tiger). Cron still technically works on modern macOS, but Apple has treated it as legacy for a long time, and it comes with real caveats on newer macOS versions around permissions and background execution.

You configure launchd with an XML property list (a "plist" file) rather than a one-line crontab entry. That's more verbose, but it buys real capability. A launchd job can be told to run:

That last point is the real headline feature: launchd is the one tool of the three that can do both cron's job and a daemon supervisor's job, in the same system, using the same configuration format.

Where launchd is strong

Where launchd is harder

Comparing All Three Side by Side

Dimension Cron Daemon / Loop launchd
What it is Time-based scheduler that fires a command and exits A process that stays alive and loops on its own macOS's native service manager: schedules AND supervises
Best for Fixed-time jobs on Linux servers ("run nightly at 2am") Always-on, reactive work ("watch this inbox continuously") Any macOS automation, scheduled or always-on
Scheduling granularity 1 minute minimum As fine as you code the loop, sub-second possible Calendar-based (minute-level) or fixed-interval, seconds possible
Keeps itself alive / restarts No Only if you build that logic in Yes (KeepAlive)
Platform Linux, macOS (legacy) Any OS, it's just a running process macOS only
Failure handling Silent by default, no retry, no alert Depends entirely on what you build Auto-restart on crash; wake-aware for missed runs

Which One Should You Actually Use

Match the tool to the shape of the problem, not the other way around.

  1. A daily or weekly report, a nightly cleanup job, a Monday-morning digest. This is a clock problem. On a Linux server, cron is fine. On a Mac, use launchd's calendar trigger instead, same idea, better failure behavior.
  2. Something needs to react within seconds of an event, an inbound lead, a new file, a webhook. This is a daemon problem. Build a process that listens or polls tightly, and put a supervisor in front of it, don't just leave it running unwatched in a terminal tab.
  3. Any of the above, but it lives on a Mac. Use launchd for both cases. It's the one tool that covers scheduled jobs and supervised daemons under a single, restart-aware system.
  4. You genuinely don't know which shape your problem is. Ask whether a person would tolerate the task happening once a day versus needing to happen the moment the triggering event occurs. That answer tells you whether you need a scheduler or a standing worker.

Why Most Business Owners Shouldn't Be Managing This Themselves

Everything above is infrastructure, not the actual business logic. A restaurant owner who wants their vendor invoices checked automatically every morning does not need to know what a plist file is, or what `KeepAlive` does, or why their overnight job silently stopped running the week the laptop's clock drifted. That's exactly the kind of decision that should be made once, correctly, by whoever builds the automation, and then never thought about again.

This is one of the quieter reasons a lot of DIY automation (a Zapier chain, a script someone's cousin wrote, a scheduled task nobody documented) eventually breaks and stays broken. Nobody built in restart logic. Nobody wired up an alert for a failed run. The job just stops, and because cron and simple scripts fail silently by default, the business doesn't find out until something downstream goes visibly wrong.

When we build a custom agent for a client, the scheduling and restart logic is part of the build, not an afterthought bolted on later. If the task is genuinely a clock problem, it gets scheduled properly with retry and alerting. If it needs to be always-on, it gets supervised so a crash doesn't mean silence for three weeks. Either way, the owner never has to know or care whether it's running on cron, a daemon, or launchd, they just get told immediately if something needs their attention.

The real question to ask yourself: if the automation you're running today silently stopped working, how long would it take you to find out? If the honest answer is "days" or "weeks," the scheduling layer is the problem, not the automation itself.

If you want to see how this fits into a broader build, our guide on how AI agent implementation actually works covers what a properly built agent looks like end to end, scheduling, monitoring, and failure handling included. And if you're weighing whether a scheduled job or an always-on agent fits your process better, our AI agent use cases for small businesses breakdown walks through both patterns in real scenarios.

Work With Us

Let us worry about the scheduling

We build the automation and the infrastructure underneath it, restarts, retries, and failure alerts included, so you never have to think about cron, daemons, or launchd again. See what a custom build costs on our pricing page, or talk it through with us directly.

Book a 30-min call

No pitch. Just the math.

Frequently Asked Questions

What is the difference between cron and a daemon?

Cron runs a job at fixed times and then exits. It has no memory of what happened before and no idea what will happen after. A daemon is a process that stays running continuously, holding state in memory and reacting to events as they happen rather than waiting for a clock to strike. Cron is a scheduler. A daemon is a standing worker.

Is launchd better than cron on a Mac?

For most new work on macOS, yes. Apple has considered cron legacy on macOS for years, and launchd can do everything cron does (StartCalendarInterval) plus what cron cannot, restart a crashed process automatically (KeepAlive), run something the instant the Mac wakes up or a file changes, and log failures through the standard system logging tools. Existing cron jobs still run fine, but new automation on a Mac should default to launchd.

When should I use a daemon instead of cron?

Use a daemon when the task needs to react within seconds, not minutes, or needs to hold state between events, such as watching a folder, listening on a socket, or maintaining a queue of in-progress work. Cron's floor is one minute and it starts each run from zero. If the job is "do this thing every night at 2am," cron or launchd's calendar trigger is simpler and cheaper. If it's "watch this inbox and respond within seconds," a daemon is the only option.

What happens if a cron job fails silently?

Nothing, by default. Cron does not retry, does not alert anyone, and does not tell you the difference between a job that ran and failed versus a job that never ran at all. Output only goes somewhere if you redirect it yourself, and even then someone has to actually read the log. This is the most common reason businesses discover an "automated" process quietly stopped working weeks after it broke.

Do I need to know any of this to run AI automation in my business?

No. This is exactly the kind of infrastructure decision that should be invisible to a business owner. A properly built automation handles its own scheduling, its own restart logic, and its own failure alerts as part of the build, so you never have to think about cron, daemons, or launchd at all. You just need to know the job runs, and to hear about it immediately if it doesn't.