Task Scheduler alternative
Task Scheduler runs commands. It does not give you a schedule you can operate.
Dagu installs as a Windows service and replaces the parts Task Scheduler never had: dependencies between jobs, retries, per-step logs, a run history, and one browser console for every server instead of an RDP session each.
# nightly-close.yaml
schedule: "0 2 * * *"
max_active_runs: 1
shell: powershell -NoProfile
steps:
- id: export
run: .\scripts\Export-Sales.ps1
retry_policy:
limit: 2
interval_sec: 300
- id: transform
run: .\scripts\Transform-Sales.ps1
depends: export
- id: load
run: .\scripts\Import-ToCore.ps1
depends: transform
handler_on:
failure:
run: .\scripts\Notify-Failure.ps1
mail_on:
failure: trueInstalls as a Windows service
PowerShell, pwsh, and cmd.exe steps
Job definitions as YAML in version control
One web console across every server
At a glance
Task Scheduler vs. Dagu on Windows Server
Declared with depends; failure stops downstream steps.
None. Order is approximated with start times.
Retries, recovery handlers, and mail notification.
A last result code, checked by a person.
YAML reviewed in git and deployed to any host.
Per-machine GUI configuration, exportable as XML.
Browser console with run history and per-step logs.
Local MMC snap-in and the Event Log, per server.
In depth
Where each tool fits
Order encoded as clock time is not a dependency
Task Scheduler triggers a task at a time. It has no concept of one task waiting for another, so teams express order by guessing durations and spacing the start times.
- The 02:30 task runs whether or not the 02:00 task succeeded, and usually feeds on whatever it left behind.
- A depends field states the order directly, so a failed upstream step stops the downstream work instead of corrupting it.
- Jobs that genuinely are independent run in parallel rather than being spaced apart out of caution.
Failures that announce themselves
A failed scheduled task sets a last result code and waits for somebody to look. Most teams find out the next morning, from the person downstream of the data.
- retry_policy retries what is transient before anyone is woken up.
- handler_on.failure runs a recovery job, and mail_on sends the notification.
- Every run keeps its own stdout and stderr per step, rather than a return code and whatever reached the Event Log.
Definitions you can review, and a console you can reach
Task Scheduler definitions live in the GUI of one machine. Exporting produces XML that nobody reviews, and checking on ten servers means ten remote sessions.
- Workflows are YAML in git, so a schedule change is a pull request and test and production can hold the same definition.
- The web UI shows current and historical runs from any browser, without an RDP session per server.
- PowerShell, pwsh, and cmd.exe are all available, so existing scripts move across unchanged.
FAQ
Practical questions before adopting Dagu
Does Dagu run as a Windows service?
Yes. The PowerShell installer can register it as a Windows service using a version-pinned WinSW wrapper, so it starts with the machine and is visible to Get-Service like any other service. Windows builds are published for amd64, 386, and arm64.
Do my existing PowerShell and batch scripts still work?
Yes. A step runs a command through PowerShell, pwsh, or cmd.exe, chosen per workflow or per step. If no shell is configured, Dagu prefers PowerShell, then pwsh, then cmd.exe. Scripts are called the same way Task Scheduler called them.
Can one Dagu manage jobs on several Windows servers?
Yes, in two ways. Workers can run on other machines and receive work from a coordinator, and remote nodes let one web UI switch between separate Dagu deployments. Either way the console is a browser rather than a remote desktop session.
Which Windows versions are supported?
Windows Server 2019 and later is the safe target. Older builds that lack AF_UNIX support still execute workflows, but the live status and stop-control socket is unavailable, so Dagu logs a warning and continues without it.
Next step
Start with one workflow.
Install Dagu, move one fragile script or agent task into YAML, and decide from a real run history.