benchdogJoin the launch list
HelpSQL Scheduler

Benchdog SQL Scheduler

SQL Agent for every edition, including the ones that never had one.

Getting started

Your first ten minutes with SQL Scheduler

  1. Install the Benchdog SQL Scheduler extension in VS Code, or the Benchdog SQL Scheduler desktop app; each carries the engine with the benchdog scheduler commands and the scheduler service.
  2. Press New Project in the SQL Scheduler panel, give it a name, pick the first server and how to sign in, and say whether to keep the history in a database; it writes a .scheduler.json file with an example job.
  3. Add jobs and steps in the file with IntelliSense, then check it with benchdog scheduler project check --project jobs.scheduler.json, which signs in to every server and looks for every file the steps use.
  4. Press Run Now on a job to run it step by step and see what each step wrote.
  5. From a terminal opened as an administrator, or with sudo, run benchdog scheduler service install --project jobs.scheduler.json so the jobs run on their schedules, and save each SQL login's password for the service when it asks you to.
  6. Check it with benchdog scheduler service status, and watch the Jobs view or the overview for each job's last run.
Questions

How to, before you buy, and when something goes wrong

How do I

How do I write a schedule?

In plain words in the project file: "every": "day" with "at": "02:00", "every": "week" with "days": "mon,thu", "every": "month" with "day": "last", or "every": "15 minutes" with "between": "08:00-18:00" and "days": "weekdays". If you know cron, give "cron": "0 2 * * *" instead, with names, lists, ranges, steps and L for the last day. Every schedule is shown in words, such as Every 15 minutes from 08:00 to 18:00 on weekdays, with its next runs.

Try one before it goes in: benchdog scheduler next --every "15 minutes" --between 08:00-18:00 --days weekdays --time-zone Europe/London prints the words, the cron and the next five runs. Each job runs in its time zone, the project's or its own, by IANA name such as Europe/London; a time the clocks skip is skipped, and a time that comes twice runs once.

How do I back up a database on a schedule?

Give a job a step with "kind": "backup" and a backup setting: type full, differential or log, and to, a folder on the server such as D:\Backups or an Azure Storage https URL. Add compress, copyOnly and checksum as you like, and keepDays to remove backups of the same kind older than that from the folder. The file is named after the database, the kind and the time in UTC, such as Shop_full_20261026_020000.bak, or .trn for a log backup.

SQL Server writes the file, not Benchdog, so the folder is one on the server that SQL Server can write to, and the login the job signs in with must be allowed to back that database up. Azure SQL Database keeps its own backups and refuses a backup step; Azure SQL Managed Instance takes copy only full backups to a URL only; SQL Server Express can not compress, so a compressed backup is written plain and the step says so.

How do I run a script, or another Benchdog tool, as a step?

A step with "kind": "sql" runs T-SQL typed in sql, or a .sql file beside the project named in script, split on GO, in the step's database; what SQL Server prints is kept as the step's output, and a batch that fails fails the step.

A step with "kind": "benchdog" runs another tool's project file beside the project, named in project: a .multirunner.json list and script, a .schemacompare.json deploy, a .datacompare.json sync, a .datascrambler.json scramble, a .datafiller.json fill or a .sqldoc.json build. One job can mix all three kinds, up to 50 steps.

How do I say what happens when a step fails?

Each step has onSuccess, which is next by default, or done to end the job well, or fail, and onFailure, which is fail by default, or next to carry on, or done. A step that fails can be tried again with retries, up to 10, and retryMinutes between tries. A step past its timeoutSeconds fails, and a job past its timeoutMinutes is stopped and marked timed out; 0 waits.

How do I run a job now?

Press Run Now on the job in VS Code, or Run now with F5 in the desktop app, and watch each step as it goes, with how many tries it took and what it wrote. From the command line, benchdog scheduler run --project jobs.scheduler.json --job "Nightly backup" runs one job, shows each step and exits with 0 only when it succeeded.

A run by hand goes in the history store, marked as started by hand, and is judged for alerts like any other. It runs as you, so a server that signs in with Entra uses your Benchdog account, and a SQL login's password is asked for when Benchdog does not have it.

How do I run the jobs on their schedules?

Install the scheduler service from a terminal opened as an administrator on Windows, or with sudo on Linux and a Mac: benchdog scheduler service install --project jobs.scheduler.json. It copies the project, its scripts and the other projects its steps run into the service's folder, so each must be beside or under the project file, and starts a service that starts with the system. Your licences are copied in too. Install again after changing any of them, or after getting a new licence; the saved passwords are kept. Installing needs a licence or a trial for SQL Scheduler, and for SQL Monitor too with --monitor; under sudo it reads the licences of the person who ran sudo. A service already running never stops on a licence: while none covers it, it keeps running the jobs and sends one note a week through its alert channels. A step that runs another tool needs that tool's licence, as running the tool by hand would. The .bat, .ps1 and .sh scripts in scripts/scheduler do the same.

Add --monitor estate.monitor.json for the same service to run SQL Monitor's collector, and --name sqljobs-prod to run more than one. The same container image runs it too, pulled as ghcr.io/simonmurrell1979/benchdog-scheduler, with scheduler run --project /config/jobs.scheduler.json as the container's command and the project, its scripts and a licences folder mounted at /config. In a terminal, benchdog scheduler run --project jobs.scheduler.json runs the jobs until Ctrl+C.

How do I see what ran?

Give the project a store, a SQL Server or Azure SQL database, when New Project asks or in the file; it can be the same database SQL Monitor keeps its history in. Every run goes there with when it was due, when it started and ended, how it went, each step and what it wrote, for retentionDays, 90 by default.

The Jobs view and the overview show each job's last run, a job's History tab lists its runs with any run in full, and the Latest runs view shows the newest across projects. From the command line, benchdog scheduler jobs --project jobs.scheduler.json lists the jobs with their next and last runs, benchdog scheduler history --project jobs.scheduler.json --job "Nightly backup" --hours 168 lists a week of runs, and --run 42 shows one in full.

How do I get an alert when a job fails?

Add channels under alerts in the project file, as for SQL Monitor: email over SMTP, a Teams webhook or a Slack webhook. Save each channel's secret with benchdog scheduler secret --project jobs.scheduler.json --channel "DBA email", which asks for it hidden, or Save Alert Channel Secret... in VS Code; an installed service keeps its own, saved with benchdog scheduler secret --service benchdog-scheduler --project jobs.scheduler.json --channel "DBA email". Then benchdog scheduler alert test --project jobs.scheduler.json sends a test to each channel.

A job that fails or times out raises an alert, critical when a backup step did not happen and a warning otherwise, said again every hour by default while it keeps failing and once more when the job succeeds again. A job skipped because the run before was still going is said once. Open alerts are kept in the history store, so SQL Monitor's alert list shows them too when the two share a store.

Before you buy

How does it relate to SQL Server Agent?

It does the job SQL Server Agent does, on editions and services that have no Agent, such as SQL Server Express and Azure SQL Database, and on SQL Server and Managed Instance as well. Its jobs live in a .scheduler.json file you keep with your code, not in msdb, and run from Benchdog's own service on a machine of your choice, which signs in to each server as the project says. It does not read or change Agent's own jobs.

How does the service sign in when nobody is logged on, and where are its secrets?

A service has no one signed in, so its servers sign in with windows, sql or managedIdentity, never Entra. On Windows the service runs as its own virtual account, NT SERVICE\benchdog-scheduler, or with --account a group managed service account such as CONTOSO\sqljobs$ or NT AUTHORITY\NetworkService; never an account with a password. On Linux it runs as a user systemd makes for it, with the rest of the system read only; on a Mac as root.

SQL login passwords are saved for the service with benchdog scheduler password --service benchdog-scheduler --server sqlhost --user sqljobs, and alert secrets with benchdog scheduler secret --service. They live in the system's store for services: encrypted with DPAPI for the machine in a credentials folder under ProgramData\Benchdog\benchdog-scheduler that only SYSTEM, Administrators and the service may read; encrypted with systemd's credentials in /etc/benchdog/benchdog-scheduler/credentials, which systemd decrypts for the service alone; or the System keychain on a Mac. Never in the project file, a log or an error.

What does it need, and where does it run?

The scheduler runs as a Windows service, a systemd service on Linux (systemd 250 or later, as on Ubuntu 24.04 and Debian 12), a launchd daemon on a Mac, or in Docker, on any machine that can reach your servers. Nothing is installed on the SQL Servers themselves. Backup steps run on SQL Server, Express and Managed Instance; on Azure SQL Database, which keeps its own backups, jobs run T-SQL and the other Benchdog tools. The history store is any SQL Server or Azure SQL database, and the scheduler makes its tables the first time.

What does it keep, and where?

The project file keeps the servers and how they sign in, the jobs, their schedules and steps, the history store, how many jobs run at a time, how long runs are kept and the alert channels, never a password or a secret. Runs, each step's output and open alerts go in the history store, in the benchdog schema beside SQL Monitor's tables when they share a database. VS Code and the desktop app keep only the paths of the project files you opened.

What happens when the scheduler was not running, or a job runs long?

A job that was due while the scheduler was not running runs once as soon as it starts, marked as a catch up run, unless the job says "missedRuns": "skip". A job due again while its run before is still going is skipped and says so, so runs never pile up. Up to four jobs run at a time by default, set with atATime. While the history store can not be reached, runs wait in memory and are kept once it can be.

Can I try it before I buy?

Yes. Every tool has a thirty day trial with every feature, and no card. Ask for one at benchdog.dev/trial with your name and email, and the trial licence arrives by email, as a line to paste and a benchdog.licence file. One trial per person covers every tool at once.

What does one licence cover?

One licence is for one person and covers the VS Code extension, the desktop app and the benchdog command, on every machine that person works from. There is no machine limit and no server count. Buying another tool reissues your licence with that tool added.

The licence shows whose it is: your name and email appear in each tool's About and account menu.

What happens when my subscription ends?

The last version released while you were paid keeps working. Only updates stop. A licence is checked offline and never expires a version it covers, so nothing stops working the day your year ends.

Which operating systems and SQL Server versions does it support?

The VS Code extensions run in VS Code 1.95 or later on Windows, Linux and Mac. The desktop apps and the benchdog command are single programs for Windows (x64), Mac (Apple silicon) and Linux (x64), with no .NET install needed. The SQL tools work with SQL Server 2017 or later, Azure SQL Database and Azure SQL Managed Instance.

Does Benchdog send my data anywhere?

No. The engine runs on your machine, reads your vaults and databases as you, and keeps the results with you. A tool contacts benchdog.dev only when you click something that needs it, such as asking for your licence, and never in the background. Licences are checked offline.

Can a tool damage my database?

Every change a tool makes runs in one transaction with XACT_ABORT on, so it all happens or none of it does. A SQL Schema Compare deploy, a SQL Data Comparer sync and a SQL Data Filler fill are each one transaction, and SQL Data Scrambler scrambles each table in one. The scripts the tools write for you to run in SSMS or sqlcmd are wrapped the same way and roll back if any batch fails. SQL Multi Runner runs your own script as it is, and wraps each database in a transaction when you tick that. Before any change, a tool says what it will do and asks first: SQL Schema Compare names the tables and columns whose rows go, SQL Data Comparer says how many rows change, and SQL Data Scrambler asks you to type the database's name. SQL Schema Compare also stops if either database changed after you read the plan. Even so, nothing replaces a backup, and the SQL Server tools can take one first.

How does it sign in?

Azure calls run as you, through a browser sign-in once or through your existing az login, in any tenant you belong to. The SQL tools use your Microsoft account, your Windows sign-in or a SQL login, and every connection is encrypted. A SQL login's password is kept until the app closes, or in your system's secure store (DPAPI on Windows, Keychain on Mac, libsecret on Linux) if you tick Remember. It is never written to a settings file, a project file or a log.

When something goes wrong

A step fails with The password for sqljobs is not saved. Save it with: benchdog scheduler password --server sqlhost --user sqljobs

The job's server signs in with a SQL login whose password Benchdog does not have. Run the command it gives; for an installed service the message names --service benchdog-scheduler too, and the command needs an administrator or sudo. On Linux the service reads its secrets when it starts, so the command ends with systemd gives the service its secrets when it starts. Restart it to use this one: sudo systemctl restart benchdog-scheduler. If the message is SQL Server refused the saved password for sqljobs., the password saved is wrong or has changed; save it again.

Installing the service says A service has no one signed in, so it can not sign in with Entra for Shop. Give each "signIn": "managedIdentity", "windows" or "sql" in jobs.scheduler.json.

Entra sign-in needs a person in the browser, which a service never has. Change that server, or the history store, to "signIn": "windows" for the account the service runs as, "sql" with a login whose password you save for the service, or "managedIdentity" for a scheduler running in Azure. The other tools' projects its steps run must sign in the same ways.

A run says Skipped: the run before was still going when this one was due at 02:00.

The job was due again before its last run ended, so this run was skipped rather than piled on top. Give the job more time between runs, or set timeoutMinutes so a run that hangs is stopped and marked timed out before the next is due. The skip is said once as an alert and kept in the history.

A backup step says Not backed up. with Azure SQL Database keeps its own backups, so Benchdog can not take one.

Azure SQL Database takes its own backups and allows no BACKUP command, so the step refuses before it tries. Use Azure's point in time restore and long term retention, or a copy of the database, and keep the job for T-SQL and tool steps. On a managed instance the message is Azure SQL Managed Instance takes only copy-only full backups, to an Azure Storage URL., so set "copyOnly": true and an https URL.

benchdog scheduler service status says The service benchdog-scheduler is stopped on an error, and starts again shortly.

The service failed and the system restarts it after 30 seconds. Read its log for why: journalctl -u benchdog-scheduler on Linux, ProgramData\Benchdog\benchdog-scheduler\logs\benchdog-scheduler.log on Windows, or /Library/Logs/Benchdog on a Mac. Then run benchdog scheduler project check --project jobs.scheduler.json --service benchdog-scheduler as an administrator or with sudo, which signs in to every server and the store as the service would and lists every file and secret it is missing.

Installing says jobs.scheduler.json uses fix.sql, which is not there. Put it beside the project file.

The service copies the project with every script and project its steps use, so each must sit beside or under the project file. Move the file there and install again. benchdog scheduler project check lists every file a step uses with no, put it beside the project file against any that is missing, and in VS Code the problem shows in the Problems panel on the step's line.

How do I get a log of what happened?

Turn on the diagnostics log: in a desktop app, Settings, then Write a diagnostics log; in VS Code, the extension's diagnostics setting; for the benchdog command, set the environment variable BENCHDOG_DIAGNOSTICS=1. Each run writes one file to the logs folder in the Benchdog folder (%LOCALAPPDATA%\Benchdog\logs on Windows, ~/Library/Application Support/Benchdog/logs on Mac, ~/.local/share/Benchdog/logs on Linux), and the last ten are kept. The desktop apps have Open logs folder, and VS Code has the Open Diagnostics Logs Folder command.

The log records sign-in requests, Azure calls, engine requests, SQL connections, times and errors. Passwords, connection strings, tokens, secret values and your data are never written, so it is safe to send to support.

The desktop app showed an error window. What now?

That is the crash window, for an error the app did not expect. Copy details puts the error and its details on the clipboard, Email support opens a message to support with them, and Open logs folder shows the crash report, which is written even with the diagnostics log off. If the error happened on a background thread the app has to close, and the window shows when it next starts.

Sign-in on Linux stops with SecureStoreUnavailableException.

Browser sign-in keeps its tokens in the desktop keyring, and that machine has none unlocked, which is common in WSL. Install and unlock a keyring such as GNOME Keyring or KWallet, or sign in with az login and turn on Use az login in Settings or pass --cli to the benchdog command. Benchdog never falls back to a plain file for tokens.

It says the server's certificate is not trusted.

The SQL Server you connected to uses a certificate your machine does not trust, which is usual for a server on your own network with a self-signed certificate. Pick Trust the server's certificate in the picker, or add --trust-server-certificate on the command line, for servers you know. For a server you do not know, install its certificate chain instead.

How do I remove a SQL password Benchdog remembered?

In a desktop app, choose Forget saved password from the menu. On the command line, run benchdog sql forget-password --server <server> --sql-login <login>. Either removes it from the system's secure store, which is the only place it was kept.

Where do I get help?

Write to support@benchdog.dev or use the support form on this site, and a person replies. Say which tool and version you were using (Help, About in a desktop app shows both), what you did and what you saw, and attach the diagnostics log if you have one.

Not answered here? Ask on the support form and a person replies.