183 lines
8.4 KiB
Markdown
183 lines
8.4 KiB
Markdown
|
|
# Veeam Backup Alerting — Current State & RPO-Based Recommendation
|
|||
|
|
|
|||
|
|
> **Date:** April 14, 2026
|
|||
|
|
> **Author:** Pulse / Cascade
|
|||
|
|
> **Status:** Recommendation — not yet implemented
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. Problem: The Current Alerting Pipeline is Noisy
|
|||
|
|
|
|||
|
|
### How It Works Today
|
|||
|
|
|
|||
|
|
Every Veeam backup alert that reaches Autotask passes through **Datto RMM** — Veeam does not create Autotask tickets directly. There are 6 Datto RMM monitors that watch for Veeam conditions (via Windows Event Log or script checks on each WNP/endpoint) and auto-create tickets when a condition is true:
|
|||
|
|
|
|||
|
|
| RMM Monitor ID | Description | Tickets (Last 30 Days) |
|
|||
|
|
|---|---|---|
|
|||
|
|
| **422325** | Veeam Agent Backup Stalled | 638 |
|
|||
|
|
| **770091** | Backup Copy Job Failed | 194 |
|
|||
|
|
| **369602** | Veeam Agent Backup Failed | 103 |
|
|||
|
|
| **369604** | Veeam Backup Job Missing or Stalled | 61 |
|
|||
|
|
| **392069** | Veeam Agent Job Finished with Failed | 58 |
|
|||
|
|
| **849483** | Veeam Server Agent Backup Job Stalled | 38 |
|
|||
|
|
|
|||
|
|
**Total: ~1,100 backup-related tickets per month** from these 6 monitors alone.
|
|||
|
|
|
|||
|
|
### Monthly Ticket Volume (Last 6 Months)
|
|||
|
|
|
|||
|
|
| Month | Backup Tickets |
|
|||
|
|
|---|---|
|
|||
|
|
| October 2025 | 461 |
|
|||
|
|
| November 2025 | 1,033 |
|
|||
|
|
| December 2025 | 1,008 |
|
|||
|
|
| January 2026 | 1,583 |
|
|||
|
|
| February 2026 | 728 |
|
|||
|
|
| March 2026 | 946 |
|
|||
|
|
|
|||
|
|
### The Core Defects
|
|||
|
|
|
|||
|
|
**1. No deduplication — one new ticket per check cycle.**
|
|||
|
|
A workstation that misses its backup today gets a new Autotask ticket every time the RMM monitor runs. `DT061` generated **41 individual tickets in 30 days** for a single laptop. In the last 30 days, **23 devices each triggered 5+ alerts**, producing **387 redundant tickets** from a single monitor.
|
|||
|
|
|
|||
|
|
**2. No schedule awareness.**
|
|||
|
|
The monitors check "has Veeam run in X days?" without knowing the job's schedule. A laptop that is legitimately offline over a weekend gets stalled alerts on Saturday and Sunday even though no backup was missed relative to its RPO.
|
|||
|
|
|
|||
|
|
**3. No auto-resolution.**
|
|||
|
|
When the underlying backup issue is fixed and the job succeeds, the open Autotask tickets are not automatically closed. Resolution requires manual action.
|
|||
|
|
|
|||
|
|
**4. No escalation logic.**
|
|||
|
|
A job that has been failing for 3 days looks identical in Autotask to one that missed a single run — both generate the same priority ticket.
|
|||
|
|
|
|||
|
|
**5. No failure context.**
|
|||
|
|
The RMM alerts contain only the device name and a generic "stalled" or "failed" label. The root cause (VBM desync, Wasabi DNS failure, VSS error, license expiry) is not surfaced in the ticket.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. Recommendation: RPO-Based Alerting via Pulse
|
|||
|
|
|
|||
|
|
### What Already Exists
|
|||
|
|
|
|||
|
|
Pulse already contains a fully-built **RPO monitoring service** at `lib/services/veeam-rpo-service.ts` and an API endpoint at `POST /api/veeam/rpo-check`. The service:
|
|||
|
|
|
|||
|
|
- Reads live job data from the Veeam VSPC sync in PostgreSQL (`veeam_backup_agent_jobs`)
|
|||
|
|
- Computes whether each job has breached its **Recovery Point Objective (RPO)** — i.e., the acceptable maximum gap since the last successful backup — based on the job's configured schedule
|
|||
|
|
- Creates **one Autotask ticket per breached job** (deduped via the `veeam_rpo_tickets` tracking table)
|
|||
|
|
- **Auto-resolves** that ticket the moment a successful backup run is detected
|
|||
|
|
- **Escalates** the ticket's priority as the RPO violation ages
|
|||
|
|
- **Categorizes** the failure reason from the Veeam failure message
|
|||
|
|
|
|||
|
|
The `veeam_rpo_tickets` table exists and is ready. It currently has 0 rows because the service has never been run.
|
|||
|
|
|
|||
|
|
### RPO Threshold Logic
|
|||
|
|
|
|||
|
|
| Schedule Type | RPO Window | Alert After | Escalate to High | Escalate to Critical |
|
|||
|
|
|---|---|---|---|---|
|
|||
|
|
| **Daily** | 24h | +4h grace = 28h | +48h | +7 days |
|
|||
|
|
| **Weekly** | 168h | +4h grace = 172h | +48h | +7 days |
|
|||
|
|
| **Continuous** | 1h | +1h grace = 2h | +4h | +12h |
|
|||
|
|
|
|||
|
|
The **grace period** (4h for daily jobs) accounts for jobs that run slightly late due to the workstation being offline, slow networks, or queued jobs on the WNP — preventing false positives for on-time jobs with minor delays.
|
|||
|
|
|
|||
|
|
### Ticket Behavior
|
|||
|
|
|
|||
|
|
| Event | Current (RMM) | Proposed (RPO) |
|
|||
|
|
|---|---|---|
|
|||
|
|
| Job misses backup | New ticket every check cycle | One ticket opened, ticket title includes hours overdue |
|
|||
|
|
| Job still failing next day | Another new ticket | Same ticket remains open, priority escalated |
|
|||
|
|
| Job still failing after 2 days | Another new ticket | Ticket escalated to High |
|
|||
|
|
| Job still failing after 7 days | Another new ticket | Ticket escalated to Critical |
|
|||
|
|
| Backup succeeds | Tickets stay open, manual close | Ticket automatically resolved |
|
|||
|
|
| Machine stale >30 days | Continuous daily alert | Skip ticket creation (likely abandoned/decommissioned machine) |
|
|||
|
|
|
|||
|
|
### Ticket Content
|
|||
|
|
|
|||
|
|
RPO tickets are filed to **Operations Triage** queue with:
|
|||
|
|
- **Title:** `[Veeam RPO] <JobName> @ <OrgName> — <N>h since last backup`
|
|||
|
|
- **Issue Type:** Backups / Veeam Agent for Microsoft Windows
|
|||
|
|
- **Description:** Job name, org, schedule, last successful backup timestamp, hours overdue, restore points available, categorized failure reason, raw error
|
|||
|
|
|
|||
|
|
**Failure categories surfaced automatically:**
|
|||
|
|
- License Expired — renew via VSPC
|
|||
|
|
- Cloud Gateway Unreachable — check `vcg01.wulfconsulting.com`
|
|||
|
|
- Backup Repository Inaccessible
|
|||
|
|
- Service Provider Maintenance
|
|||
|
|
- Network/Connectivity Error
|
|||
|
|
- Backup Job Timeout
|
|||
|
|
- VBM desync (raw message)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. Estimated Impact
|
|||
|
|
|
|||
|
|
| Metric | Current (RMM) | Projected (RPO) |
|
|||
|
|
|---|---|---|
|
|||
|
|
| Tickets/month (backup) | ~950–1,100 | **~50–150** (one per new breach, not per check) |
|
|||
|
|
| Duplicate tickets for same device | Up to 41/month | **0** (deduped by job UID) |
|
|||
|
|
| Manual ticket closures required | All | **0** (auto-resolved on success) |
|
|||
|
|
| Failure root cause in ticket | No | **Yes** (categorized + raw message) |
|
|||
|
|
| False positives (offline weekend) | Yes | **Minimal** (RPO + grace window) |
|
|||
|
|
| Escalation based on severity | No | **Yes** (medium → high → critical) |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. Implementation Steps
|
|||
|
|
|
|||
|
|
### Step 1 — Enable Veeam Sync
|
|||
|
|
|
|||
|
|
The RPO service reads from the Veeam VSPC sync tables. The sync schedules already exist but are disabled:
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
UPDATE sync_schedules SET is_enabled = true WHERE sync_type IN ('veeam-incremental', 'veeam-full');
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
The 30-minute incremental sync keeps job status current enough for RPO evaluation.
|
|||
|
|
|
|||
|
|
### Step 2 — Add RPO Check Schedule
|
|||
|
|
|
|||
|
|
Add a schedule entry to run the RPO check every 2 hours:
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
INSERT INTO sync_schedules (id, sync_type, cron_expression, is_enabled, description)
|
|||
|
|
VALUES ('veeam-rpo-check', 'veeam-rpo-check', '0 */2 * * *', true, 'Veeam RPO check — creates/escalates/resolves backup tickets');
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
The scheduler needs to handle the `veeam-rpo-check` sync type by calling `POST /api/veeam/rpo-check`.
|
|||
|
|
|
|||
|
|
### Step 3 — Disable the 6 Datto RMM Backup Monitors
|
|||
|
|
|
|||
|
|
In Datto RMM, disable ticket creation (or disable the monitors entirely) for the 6 monitors listed in Section 1. This eliminates the duplicate ticket stream. The monitors can remain as alerting events in RMM itself without creating Autotask tickets, if desired.
|
|||
|
|
|
|||
|
|
> **Do not disable the monitors before the RPO service is confirmed working.** Run both in parallel for at least one week to validate coverage.
|
|||
|
|
|
|||
|
|
### Step 4 — Dry Run Before Go-Live
|
|||
|
|
|
|||
|
|
The RPO check endpoint supports a dry-run mode that shows what it *would* do without creating any tickets:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl -X POST https://pulse.wulfconsulting.cloud/api/veeam/rpo-check \
|
|||
|
|
-H "Content-Type: application/json" \
|
|||
|
|
-d '{"dryRun": true}'
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
This returns `wouldCreate`, `wouldResolve`, `wouldEscalate`, and `wouldSkipTooOld` counts along with the full job status list.
|
|||
|
|
|
|||
|
|
### Step 5 — Validate & Monitor
|
|||
|
|
|
|||
|
|
After enabling, confirm via Autotask that:
|
|||
|
|
- RPO tickets are appearing with `[Veeam RPO]` prefix in the title
|
|||
|
|
- Resolved tickets are auto-closing when backups succeed
|
|||
|
|
- Ticket count is trending down from the ~1,100/month baseline
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. What Is NOT Changing
|
|||
|
|
|
|||
|
|
- **Backup infrastructure is unchanged** — WNPs, Veeam agents, Wasabi, VSPC all remain identical
|
|||
|
|
- **Datto RMM monitoring** — RMM continues to monitor Veeam; only the ticket-creation action on those monitors is disabled
|
|||
|
|
- **Server/VM backup alerting** — this recommendation is scoped to workstation jobs only; server and VM backup alerting should be evaluated separately
|
|||
|
|
- **Restore workflows** — restore requests continue to be filed as standard Autotask tickets by users/staff
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
*This document was produced by analyzing Autotask ticket data and the Veeam VSPC sync in the Pulse PostgreSQL database. The RPO service implementation is in `lib/services/veeam-rpo-service.ts` and `app/api/veeam/rpo-check/route.ts`.*
|