Backup Job Health · git:20260804.5567c51 · 2026-08-04 · sha256 219f87c7b40697eb
Backup Job Health git:20260804.5567c51A
Immutable. This exact content is served forever at /api/v1/blob/219f87c7b40697eb.
--- name: "Backup Job Health" description: > Portfolio-wide backup job health across whatever BCDR and SaaS-backup tools are connected: the two structurally different job models (image-based appliance backup vs. SaaS-data snapshot backup) and how to normalize them into one health record per protected unit, why a live consecutive-failure streak matters more than a trailing success rate, the missed-versus-failed distinction and its different root causes, and the two storage-trending risk patterns (approaching capacity, anomalous growth). when_to_use: >- When assessing whether backup jobs are actually running successfully across a portfolio, rather than checking one client's one appliance in isolation. Use when: backup health, backup job failures, missed backups, backup success rate, failed backup jobs, backup storage trending, is this client's backups running, backup audit, backup job status. --- # Backup Job Health ## Overview "Backups are running" is the single most-assumed, least-verified fact in an MSP's environment. A backup job that failed silently three nights ago looks identical, from a distance, to one that's been succeeding for months — nobody notices until a restore is needed and there's nothing current to restore from. This skill is the recurring, portfolio-wide sweep that catches that gap before it becomes an incident: job success/ failure rate, missed-backup detection, and storage-consumption trending, rolled into one normalized view across every backup and BCDR tool an org has connected. This skill is about whether backups are *happening*. It is deliberately narrower than disaster-recovery readiness as a whole — it does not assess whether a backup, once taken, is actually recoverable (see `restore-test-verification`), and it does not assess whether the retention window or cadence in place actually satisfies a contracted requirement (see `retention-rpo-compliance`). Treat this as the first, most frequent layer of the DR assurance stack: if jobs aren't running, nothing downstream matters yet. ## Anti-triggers - **Backup Radar's own health records** — ScalePad already aggregates and scores backup results across vendors; use `scalepad-backup-radar` when the question is what that API returns. This skill normalizes across every connected backup tool, including orgs that have no Backup Radar at all. - **One platform's job, alert, or storage data** — use `datto-bcdr-api-patterns`, `datto-saas-protection-api-patterns`, `spanning-api-patterns`, or `unitrends-api-patterns` for a single vendor's request shapes and field names. ## Key Concepts ### Two fundamentally different job models Backup and BCDR vendors protect data in two structurally different ways, and treating them as the same "job" concept produces misleading comparisons: - **Image-based appliance backup** (e.g. Datto BCDR / SIRIS / Alto, Unitrends) — protects physical or virtual servers/workstations by taking periodic block-level or image-level snapshots to a local appliance, then syncing offsite/to the cloud. A "job" here is a scheduled backup of one protected agent/asset on one appliance. Health signals include: last successful local backup, last successful offsite sync, and (for Datto BCDR specifically) screenshot/boot verification status — see `restore-test-verification`. - **SaaS-data snapshot backup** (e.g. Datto SaaS Protection, Spanning) — protects cloud application data (Microsoft 365 mailboxes/OneDrive/SharePoint/Teams, Google Workspace, Salesforce) by taking periodic API-level snapshots of tenant data. A "job" here is a scheduled backup pass across a set of protected seats/users for a tenant. There is no "appliance" and no local/offsite sync distinction — health signals are seat coverage (are all licensed users actually being backed up) and per-run success/failure across the tenant. Normalize both into a single health record per protected unit (appliance-agent pair, or tenant-seat set) with the same fields — last successful run, run status, and failure streak — even though the underlying job mechanics differ. Don't force a one-size-fits-all metric like "backup window duration" that only makes sense for one model. ### Job success/failure rate For each protected unit, compute the success rate over a rolling window (default: last 30 days unless the org has a documented preference) and, more importantly, the **current consecutive-failure streak**. A unit with a 96% success rate over 30 days but a live 4-night failure streak right now is a more urgent problem than a unit with 90% success and no current streak — trailing averages hide exactly the thing that matters most: is it broken *right now*. ### Missed-backup detection A missed backup is distinct from a failed backup: a failed backup ran and errored; a missed backup never ran at all (no job execution recorded for the expected window). Both matter, but they point to different root causes — a failed job usually means an in-scope problem (disk full, credential expired, source unreachable), while a missed job often means a scheduling, licensing, or connectivity problem that's more structural (the agent/connector isn't checking in at all). Report them as separate categories rather than merging them into one "unhealthy" bucket, since the remediation path differs. ### Storage-consumption trending Track local and offsite/cloud storage consumption per appliance (or per SaaS tenant, where the vendor exposes storage/quota data) over time. Flag two distinct risk patterns: - **Approaching capacity** — an appliance trending toward its local storage limit, which risks retention truncation (older recovery points get purged early to make room) even while nightly jobs continue to report success. This is a silent retention risk — see `retention-rpo-compliance` for how a storage-forced retention cut interacts with a contracted retention requirement. - **Anomalous growth** — a sudden, unexplained jump in daily change-rate/storage consumption, which can indicate anything from a legitimate data-growth event to ransomware encryption activity happening on the protected source. Anomalous growth is worth flagging even when it isn't yet a capacity problem, because of what it might indicate about the protected system. ### If no backup/BCDR tool is connected State plainly that job health cannot be assessed: "No backup or BCDR connector is connected through the gateway, so there's no backup job data to audit." Do not fabricate success rates, job counts, or storage figures. ## Common Workflows ### Full portfolio sweep 1. Discover connected backup/BCDR tools via `conduit__search_tools` — don't assume which of Datto BCDR, Datto SaaS Protection, Spanning, or Unitrends (or others) are live for this org. 2. For each connected tool, pull the protected-unit list (appliances/agents for image-based tools; tenants/seats for SaaS-snapshot tools) and each unit's recent job history. 3. Normalize into one health record per protected unit: last successful run, current run status, consecutive-failure streak, and (where available) storage/quota state. 4. Bucket into: actively failing (current failure streak), missed (no run recorded for expected window), storage-at-risk, and healthy. 5. Report worst-first: longest active failure streak, then missed backups, then storage risk. ### Targeted client check 1. Resolve the client to its protected units across whatever connected tool(s) cover them (a client may have both an on-prem appliance and a SaaS-backup tenant). 2. Pull and normalize job history for just that client's units. 3. Report success/failure rate, active streaks, and storage state for that client only. ## Error Handling - **No backup/BCDR connector connected:** stop and say so; do not fabricate job status. - **A connected tool doesn't expose storage/quota data:** report job success/failure normally and mark the storage-trending section "unable to verify — connector does not expose storage data" rather than omitting it silently. - **A protected unit exists in inventory but has no job history at all:** treat this as a missed backup, not a gap in the report — a never-run job is exactly the kind of silent failure this skill exists to catch. ## Best Practices - State the rolling window used (default 30 days) explicitly in every report. ## Related Skills - [Restore-Test Verification](../restore-test-verification/SKILL.md) — whether a successfully-run backup is actually recoverable; this skill only confirms the job ran, not that its output is usable. - [Retention/RPO Compliance](../retention-rpo-compliance/SKILL.md) — whether the retention window and backup cadence in place satisfy a contracted requirement; relevant when storage-forced retention truncation is detected here.