TRUSTIVAN is self-hosted: there is no hosted SLA, because there is no hosted service to hold one against. What follows are the objectives the shipped alert rules are already tuned to — made explicit so an operator can report against them, not a new promise layered on top. Each number below is the threshold a rule in infra/monitoring/alerts.yml already fires on; change the rule and this page is describing something else.

Availability

Target: the API is reachable 99.9% of the month (43m 43s of allowed downtime). Measured as up{job="trustowl-api"} — Prometheus’s own scrape result, not a synthetic check. TrustOwlAPIDown fires after 2 minutes of failed scrapes, which is the objective’s detection latency: an outage inside the error budget is invisible for up to 2 minutes before it starts being tracked as an incident.
A second, narrower objective sits inside this one: fewer than 5% of served requests are 5xx, over any rolling 10-minute window (TrustOwlAPIErrorRateHigh). A deployment can be “up” by the reachability objective — Prometheus can scrape /metrics — while failing this one, if the database is unreachable and every request 500s. Both are tracked because they fail independently: see /ready for why a readiness failure and a scrape failure are different events.

Latency

Target: p95 API request latency under 2 seconds, over any rolling 10-minute window (TrustOwlAPILatencyHigh). This covers request-response endpoints only — the fast path is a few milliseconds and the slow path is a database query, never a scan, which is asynchronous and excluded from this histogram by construction (trustowl_http_request_duration_seconds only observes HTTP handlers; see the metrics section). Target: a dispatchable scan is claimed within 10 minutes of becoming eligible (TrustOwlScanQueueAgeHigh, trustowl_scans_queued_age_seconds). There is deliberately no target for total scan duration — pulling and unpacking a 4 GB image is a different latency budget than a 40 MB one, and a single number would either be so loose it catches nothing or so tight it pages on every large image. Track trustowl_scans_duration_seconds per target kind instead, and set a threshold against your own fleet’s image size distribution if you want one.

What is not an SLO here

Scan failure rate (TrustOwlScanFailureRateHigh, >25% over 15 minutes) is an anomaly threshold, not an objective — a healthy fleet’s failure rate is driven by expired registry credentials and malformed images, which is customer behaviour TRUSTIVAN does not control and should not be held to a target for. It pages because a sudden rise usually means something in the platform broke (the vulnerability database, worker egress), not because some fraction of failures is the goal. Backup and restore-drill freshness (TrustOwlBackupStale, TrustOwlRestoreDrillStale) are operational hygiene, covered in docs/deployment/backup-and-recovery.md in the repository rather than here — they are pass/fail per run, not a rate to budget against.

Computing your own error budget

Every objective above is one Prometheus query away because the alert expressions already compute the numerator; avg_over_time or sum(rate(...)) over a longer window turns “did this fire” into “how much of the budget did it spend”. Import infra/monitoring/dashboard.json from the repository into Grafana, point it at the same Prometheus, and the panels already plot the raw series; add a 30-day window panel with the formula above for the monthly figure.