Backups
The Backups page answers one question per database: if this server died right now, how much committed work would be lost, and could it be restored at all?
Where the numbers come from
msdb.dbo.backupset on each monitored instance, refreshed by the background
infrastructure snapshot. That table records only successful backups — there is no
"failed backup" row to look for. A failure shows up here as an age: the last full or log
backup simply stops getting newer. (The failure message itself does exist, in the SQL
Server error log as error 3041, and the error-log harvester picks it up.)
msdb is searched over a bounded window (90 days by default). A database with nothing in that window is reported as "no full backup in the last 90 days" rather than "never" — because a bounded search cannot honestly claim "never".
The status levels
| Level | What it means |
|---|---|
| Critical | No backup at all, a full backup past its limit, or — most importantly — a FULL/BULK_LOGGED database whose log is not being backed up. |
| Warning | Restorable, but the newest full or differential is old enough that a restore would have to replay a long chain of log backups. |
| OK | Inside the configured thresholds. |
| n/a | The question does not apply: the database is offline, restoring, or otherwise not in a state that can be backed up. |
Why the log rule outranks everything else
A database in FULL recovery whose transaction log is never backed up does not merely
lack restore points. Its log cannot be truncated and grows until the disk is full, at
which point writes stop with error 9002. That is not a reporting gap, it is a pending
outage, and it is scored above a missing full backup for exactly that reason.
Databases in SIMPLE recovery are never faulted for missing log backups — their log
cannot be backed up at all.
Thresholds
Configured under BackupMonitoring in appsettings.json. The defaults describe the
common shape rather than an aspiration:
| Setting | Default | Meaning |
|---|---|---|
FullMaxAgeHours |
168 (7 days) | Weekly full backup |
DiffMaxAgeHours |
24 | Once the full is older than this, a differential is expected |
LogMaxAgeMinutes |
90 | Hourly log backup, with room to be late |
NewDatabaseGraceHours |
24 | A freshly created or restored database is not faulted immediately |
LogMaxAgeMinutes is deliberately 90 rather than 60. With an hourly log job and a
60-minute limit, the age crosses the threshold in the minutes before every run — an
alert that fires once an hour, for ever, on a correctly configured server.
Copy-only backups
A full backup taken with COPY_ONLY is perfectly restorable, but it does not become
the base for differentials. A server backed up exclusively with copy-only fulls therefore
looks healthy while having no differential base at all. Those databases carry a
copy-only badge on the list.
Per-database history
Clicking a row reads the recent backups of that database live from msdb: type, size, compressed size, duration and device. A device name that looks like a GUID rather than a path is a third-party tool writing through the virtual device interface — the backup is real, it just is not a file.
Alerts
One alert per server, not per database: a nightly job that failed on a server with sixty databases failed once. The alert carries the number of databases in breach and the worst one's reason, and it resolves itself once every database is back inside its thresholds — unlike an error-log alert, backup state is a condition rather than an event.
Azure SQL Database
There is no msdb, so there is no backup history to read. Backups there are the platform's responsibility and the page skips those instances.