# SLOs: objectives, error budgets and unmeasured time

> Set a target on an uptime check, monitor, heartbeat or spans; how Belvador counts good and bad, coverage, statuses and where the data lives.

A **service level objective (SLO)** is a promise you make about one thing Belvador already measures: "the checkout API answers 99.9 % of the time", "the nightly export succeeds 99 % of runs", "95 % of `GET /api/orders` requests finish under 300 ms". Belvador counts good and bad over a rolling window, shows how much **error budget** is left, and [alerts you](https://belvador.dev/en/docs/slos/alerts) when the budget is burning too fast — long before it is gone.

| You want to know when… | Use |
|---|---|
| A page or API is down right now | An [uptime check](https://belvador.dev/en/docs/uptime/quickstart) |
| A job did not run or failed | A [monitor](https://belvador.dev/en/docs/monitors/overview) |
| Reliability over weeks is slipping, before users notice | An SLO (this page) |

## 1. Create an SLO

Open **SLOs → New SLO** and work through the four steps.

1. **Source** — what is counted:

   | Source | Good | Total | Counted by |
   |---|---|---|---|
   | **Uptime check** · availability | rounds that were Up or Degraded | rounds with a definite result | Belvador, from the check's results |
   | **Uptime check** · latency | rounds answered within your threshold | rounds with a definite result | Belvador |
   | **Monitor** | runs that ended OK | runs that ended OK, failed, timed out or were missed | your node |
   | **Heartbeat** | deadlines met by an on-time ping | deadlines that passed | Belvador |
   | **Spans** · availability | `SERVER` spans without error status | `SERVER` spans of the service (and operation) | your node |
   | **Spans** · latency | `SERVER` spans faster than your threshold | `SERVER` spans of the service (and operation) | your node |

   Spans count only the `SERVER` kind, so a request is not counted twice through its client and internal spans. A monitor or spans SLO can be limited to one **environment**; empty means every environment.

2. **What counts as good** — availability, or latency with a threshold of 1–60000 ms (uptime checks and spans only).
3. **Objective** — between 90 % and 99.99 %, over a rolling window of 7, 28, 30 days. The form shows the budget this gives you, for example "Error budget: 43.2 minutes per 30 days" for 99.9 %.
4. **Alerts** — which burn levels may alert; see [Burn-rate alerts](https://belvador.dev/en/docs/slos/alerts).

Belvador measures from the moment you save; history from before is not filled in. A new SLO needs at least 60 measured minutes before it shows a verdict. How many SLOs a workspace can have depends on its plan.

## 2. Error budget

The **error budget** is the bad you are allowed: `1 − objective` of the window. How it is spent depends on the source, using the two OpenSLO budgeting methods:

- **Timeslices** (uptime checks) — the budget is time. 99.9 % over 30 days allows 43.2 bad minutes; every bad interval spends its length.
- **Occurrences** (monitors, heartbeats, spans) — the budget is a share of events. 99 % allows 1 bad run in every 100.

**Budget left** is shown in percent and can go below zero when the SLO is already missed. **Attained** is good ÷ total over the window, always rounded down, so a value just under the target never reads as meeting it.

## 3. Unknown time never counts as good

Some minutes cannot be judged: the node was offline, an uptime round had too few regions, the source was paused, or nothing ran. Belvador leaves those minutes **out of both good and total** — they are never counted as good.

**Coverage** is the share of the window Belvador could measure. Below 90 %, the SLO shows **Not enough data** instead of a number, and it sends no alerts. Gaps are drawn as gaps in the budget chart.

## 4. Statuses

| Status | Meaning |
|---|---|
| **Within budget** | Burning slower than any alert threshold |
| **Burning** | A slow-burn (ticket) threshold is exceeded |
| **Fast burn** | A fast-burn (page) threshold is exceeded |
| **Budget exhausted** | No budget left in the window |
| **Not enough data** | Coverage below 90 %, or too little measured time yet |
| **Paused** | Not judged and not alerting, until the time you chose or until you resume |

## 5. Editing an SLO

Every save creates a new **revision**, listed on the SLO page. Changing the name, description, objective, window or alert policy keeps the history. Changing **what is counted** — the source, its filters, the indicator, the latency threshold or whether public sources count — starts the budget again from that moment, because old counts no longer mean the same thing. The form warns you before you save.

An SLO [imported from an OpenSLO file](https://belvador.dev/en/docs/slos/openslo) can only be changed by importing the file again.

## 6. Public sources

Some data can be sent with a key that is public by design — for example check-ins sent with a browser DSN. Anyone who can read your page could send fake values and move the SLO. Such data is **not counted** unless you turn on **Allow public sources** for that SLO; the SLO then carries a warning label.

## 7. Where SLO data lives

- **Kept by Belvador:** the definition and its revisions, and **counts only** — per SLO and minute, how many were good and how many were counted. Minute counts are kept for 3 days, hourly counts for 90 days. Windows up to 6 hours are judged from minute counts, longer ones from hourly counts. Status and alert history are kept with them.
- **Never sent to Belvador:** span contents, check-in contents or anything else from your node. For monitor and spans SLOs your node receives only the SLO's id and filter, counts locally, and sends `(SLO id, good, total)` per minute. It never learns the SLO's name.
- Spans are counted 3 minutes after each minute ends, so late batches still land in the right minute.

## 8. Not in this version

Calendar-month windows, SLOs combining several sources, weighting by sampling rate and scheduled exclusions are not supported. For planned maintenance, [mute or pause](https://belvador.dev/en/docs/slos/alerts#pause-and-mute) the SLO.
