SLO measurements
An SLO answers three questions: what counts as success, how often it must succeed, and over what window. Define these together in one ServiceLevelObjective.
- Its
spec.measurementselects the metric and eligible events; the target, window and burn-rate policies describe the objective. - A critical user journey links the SLOs that protect a user experience.
- There is no separate measurement to name, save or version in the default flow. Measurement edits create a new revision of the same SLO. Previous revisions retain their original definitions and collected evidence.
Create an SLO in the portal
- Open Service level objectives → Define objective → Measurement.
- Enter the SLO identity, project, service and configured telemetry connection. Choose the metric and the labels selecting eligible events.
- Choose successful-event labels, or a classic histogram and latency threshold. State where events are observed and what that observation misses. Set measurement and scrape intervals.
- Set the target percentage, rolling window, lifecycle and any burn-rate alert policies. Only committed SLOs emit burn alerts; other lifecycles keep measuring. Each policy has its own severity, short and long windows, threshold and pending duration.
- Select Verify telemetry and review SLO. Nines checks recent metric metadata and observed series and generates one SLO YAML definition. Nothing is saved by this preview.
- Review the exact definition, telemetry interval and warnings, acknowledge the measurement semantics, then select Save reviewed SLO.
- The telemetry connection policy controls delivery: with automatic deployment enabled, saving queues its rules without another apply action. Otherwise use Rules → Apply reviewed rules. Inspect configuration and runtime evidence separately. See automatic deployment.
- Edit an existing structured measurement in the same Measurement tab.
- The reviewed update keeps
metadata.name, increments its revision and resets active measurement evidence when semantics change. - A manual edit through this form omits earlier intent provenance; earlier revisions retain it.
- Use an intent conversation for a new agent-assisted proposal with fresh confirmation and approval.
- The reviewed update keeps
- See measurement quality for count/freshness requirements and cohort inspection, and error-budget response policies for operational decisions.
Lifecycle and alert eligibility
spec.lifecycleacceptsexperimental,aspirational,committedordeprecated. Omitting it preserves committed behavior. Choose experimental while validating instrumentation, aspirational for a target you are working toward, committed for an operational commitment, and deprecated while retiring an objective.- All four lifecycles retain SLI measurements, error-budget arithmetic, history and recording rules.
- Only committed generates burn alert rules and emits Nines burn events.
- Noncommitted objectives display Alerts disabled instead of suggesting a successful alert evaluation. Lifecycle changes create ordinary reviewed revisions.
- They preserve measurement evidence; a change of population, source or measurement semantics still starts fresh coverage.
- Promoting to committed produces a review warning.
- A definition save does not instantly disable alerts in an external evaluator.
- With automatic rule delivery, wait for the revised group to be loaded and evaluated.
- In manual mode, apply the reviewed rules.
- Until that succeeds, the previous Prometheus/Mimir group can still alert.
- Nines does not manage existing Alertmanager notifications or silences.
- Each burn policy may set
minEventsto a nonnegative count.- Both its short and long windows must contain at least this many eligible events, in addition to sufficient coverage and nonzero traffic.
- Omit it or use zero for the existing behavior.
- This is a traffic guard, not a statistical confidence interval; scrape-based counter increases can be fractional estimates.
- Choose it from the service's traffic and response needs rather than copying a universal value.
For example, add these fields to the complete YAML below:
spec:
lifecycle: experimental
policies:
- name: fast-burn
severity: critical
shortWindow: 5m
longWindow: 1h
burnRate: 14.4
forSeconds: 120
minCoverage: 1
minEvents: 100
- This excerpt illustrates the optional fields; it is not a complete SLO.
- Thresholds above
1 / (1 - target)are rejected because even 100% failed events cannot reach them. - For a 90% target, the maximum burn rate is 10, so a copied 14.4 threshold would never fire.
- Thresholds above
The offline CLI accepts the same fields. For a single-policy starter:
nines init slo --name api --lifecycle experimental --min-events 100 --out api.slo.yaml
nines validate --offline -f api.slo.yaml
- Edit named
policiesin YAML; single-policy override flags deliberately reject ambiguous updates to a list.--no-policyremoves either form. When an SLO retains intent provenance, its lifecycle and policy fields must agree with that reviewed intent. - Historical burn crossings remain numerical previews even when lifecycle disables alerts.
- In Nines, insufficient coverage or traffic interrupts pending and never establishes recovery of a firing episode.
- Prometheus/Mimir use their native alert-state behavior: an absent alert expression can resolve an alert.
- Validate external notification routing and missing-data monitoring separately.
One YAML definition
See the complete availability SLO and latency SLO, including two severity-based burn policies. For example:
apiVersion: nines.dev/v1alpha1
kind: ServiceLevelObjective
metadata:
name: request-success
project: production
spec:
displayName: API request success
service: api
source: primary
target: 0.999
windowSeconds: 2419200 # Rolling 28 days
stepSeconds: 60
measurement:
type: availability
metric: http_requests_total
labels:
service: api
environment: production
successLabels:
status: "200"
scrapeIntervalSeconds: 15
observationPoint: Completed API requests, including failures. Requests that never reach the server are not observed.
policies:
- name: fast-burn
severity: critical
shortWindow: 5m
longWindow: 1h
burnRate: 14.4
forSeconds: 120
minCoverage: 1
- name: sustained-burn
severity: warning
shortWindow: 30m
longWindow: 6h
burnRate: 6
forSeconds: 300
minCoverage: 1
sourceidentifies a tenant-configured connection, not a provider URL or credential.- Label filters are exact string matches.
labelsselects all eligible events;successLabelsadds the matches for good events. - Availability currently supports positive equality success criteria, not regex/negation.
- Use custom queries when the measurement requires more expressive logic.
countFrom: histogramselects a classic histogram's_countfor event counting. - Latency uses the exact
thresholdSecondsbucket and_counttotal; missing buckets, quantiles and native histograms are rejected.
- Label filters are exact string matches.
stepSecondsmust be 1–3600 and divide the rolling window.- A rolling window may be at most 31 days and contain at most 100,000 intervals; 28 days with 60-second intervals is 40,320 intervals.
- The positive scrape interval must satisfy the provider-window constraints.
- Short/long burn windows must align with the measurement interval.
- PromQL selectors and window calculations are generated deterministically; do not supply
providerWindow, custom queries ormeasurementBindingalongsidemeasurement.
CLI, API and agents
# Offline validation and rule generation require no server or model.
nines validate --offline -f examples/request-success.slo.yaml
nines rules generate --offline -f examples/request-success.slo.yaml --tenant production
# Connected read-only verification against the tenant's configured source.
nines telemetry verify -f examples/request-success.slo.yaml --context production --agent
# Review and apply the same SLO. Zero means create; edits need the current revision.
nines plan -f examples/request-success.slo.yaml --context production --agent
nines apply -f examples/request-success.slo.yaml --expected-revision 0 --context production --agent
POST /api/slos/compileaccepts one versioned SLO asapplication/yamlorapplication/json.- It returns the unchanged self-contained manifest/YAML, compiler version, measurement digest, manifest digest, bounded telemetry evidence and warnings.
- It writes no resource and creates no hidden binding.
- The Go client exposes
CompileMeasurement; MCP exposes read-onlyverify_slo_measurement.
- For intent workflows, put the same
measurementandstepSecondsinside the intent.- The deterministic planner verifies that its outcome, entire population and latency threshold match the goal.
- In a conversation, an owner/editor confirms the exact
measurementDigestandintentDigestat the currentexpectedVersion, then separately reviews and approves the frozen change-set digest before apply. - A model cannot confirm a measurement or approve/apply changes.
- Editing the goal or measurement invalidates prior selection, evidence and approval. Governance and rollback remain explicit.
- The operator accepts the same inline measurement in SLOs and intent CRs.
- It renders/reconciles without reading a binding CR.
- Standalone Kubernetes RBAC and GitOps govern changes; server conversation approvals are not implicitly attached to arbitrary GitOps edits.
Advanced and existing definitions
- Direct
goodQuery/totalQueryandproviderWindowdefinitions remain available through Settings/YAML for advanced queries.- An explicitly authored legacy
MeasurementBindingand revision-pinned reference remain accepted for existing shared contracts, but they are not a prerequisite and have no primary navigation entry. - Nothing silently creates or updates one during the default flow.
- An explicitly authored legacy
- Telemetry metadata and observed series verify instrument compatibility.
- They do not prove business correctness, excluded requests, current traffic, complete historical coverage or end-to-end user success. Missing evidence remains unknown.
- The observation point, retries and eligible-event semantics require human review.
Reading observed SLI attainment
- The portal shows the measured SLI percentage next to the SLO target in objective lists, headers and linked-objective views.
- For example,
99.950% SLIwith a99.900% targetandPartial windowmeans that the ratio is available but the full rolling window has not yet been observed. - The chart shows one Measured SLI series against the SLO target. It measures the rolling objective window.
- Dashed segments mean that the window has incomplete history; solid segments have complete history.
- Incomplete history is a qualification of that series, not a separate metric.
- Interval SLI remains in the selected-interval details.
- Coverage reports how much of that window contains measurements; newly created long-window SLOs can have valid ratios while history accumulates.
- For example,
No SLI datameans usable measurements are missing.No trafficmeans samples were received but their total eligible-event count is zero, so no attainment percentage can be calculated.- Missing budget data is not displayed as an exhausted progress bar.
- Alert state and recording-rule deployment are separate from measured attainment.
- Showing partial measurements does not weaken alert coverage requirements or establish full-window compliance.
Read measurements from a telemetry connection
- Nines reads existing application metrics through the configured Prometheus or Mimir query API.
- The background collector runs every 15 seconds for SLOs with a source and saved measurement queries.
- Nines is not a replacement for scraping applications or sending telemetry into those systems.
- Open an SLO and use Source measurements → Read latest measurements to collect a bounded recent range immediately.
- The source, credentials and Mimir organization come from trusted server configuration.
- The saved SLO defines the good/total selectors; the server chooses completed, step-aligned times with a one-step delay.
- The recent range covers up to 15 minutes, or one step for larger steps, within the SLO window.
- Collected values refresh attainment and charts; this operation does not deploy rules or edit the SLO.
- Use Browse metrics in this source to list up to 100 recent metric names, optionally narrowed by prefix.
- Select a metric to inspect its observed labels.
- The browser uses bounded 15-minute index lookups, so series presence alone does not prove fresh traffic or a valid success definition.
- Browsing never substitutes a metric into your SLO.
- Editors can open the existing edit/review flow after inspecting the evidence; viewers can browse but cannot collect or edit.
- If a connection works but the saved selectors match no data, the panel reports an empty result.
- For example, the integration playground exports
playground_requests_total{code="200"}andplayground_requests_total{code="500"}. - An SLO querying
http_requests_totalwill not measure that fixture. - Use the metric that actually represents your intended application and review its labels; do not substitute an unrelated metric merely to produce a percentage.
- For example, the integration playground exports
For a recent read from the CLI:
nines collect api-availability --recent --tenant production --agent
- The equivalent API call is
POST /api/slos/api-availability/collectwith{"recent":true}.- The existing explicit
from/tobody remains available for backfills. Do not combine the two modes. - Collection commits measurement data, requires an editor or owner, and still checks tenant authorization, CSRF for cookie sessions and measurement revision safety.
- An empty successful query is not an attained SLO; zero-traffic samples also do not imply success.
- The existing explicit
Chart accessibility
- Hover or tap the chart to inspect an observation. Keyboard users can focus the chart directly; no separate time-point scrubber is required.
- Arrow keys select adjacent observations; Home/End select the first/last, and Page Up/Down move through the range.
- The chart announces the selected timestamp, measured value, incomplete-window coverage when applicable, and target. A compact readout shows the selected time and values; raw per-sample tables are not part of the chart interface. UTC is retained consistently with the date-range controls.
- Burn-rate windows use different stroke patterns as well as color; below-target complete-window values use triangular markers.
- Chart labels and controls use theme-aware colors checked against WCAG 2.2 contrast requirements.
- Panels grow with their text rather than clipping readouts.
- Date/time fields, focus indicators and tables remain available for keyboard use.
- Automated semantic checks and light/dark token-contrast tests cover these chart components; they do not establish conformance of every product screen or assistive-technology combination.
Burn alert window durations
- Prefer
shortWindow: 5mandlongWindow: 1hin policies.300sand1h30mare also accepted. - Use positive whole-number
h,mandscomponents. Day units, datetime strings, fractional components and subsecond units are not accepted for these windows. - Existing
shortWindowSecondsandlongWindowSecondsinputs remain supported. Specify exactly one representation per window; supplying both is an error. - YAML exports use readable duration fields. Runtime JSON responses, stored policy values and deterministic calculations retain numeric seconds.
forSeconds,windowSecondsand other existing fields keep their current names and units. - The CLI, API, MCP resource apply and Kubernetes operator use the same parser and policy constraints. Duration syntax does not change burn-rate thresholds, alignment requirements or evaluation behavior.
Delayed scheduled collection
- Automatic collection follows its last successful source watermark when a polling round is delayed. Each request is capped at 300 intervals and the SLO retention boundary.
- Catch-up queries fetch actual telemetry; they do not turn gaps into zero errors or force an alert to recover.
- Longer outages and late telemetry outside the bounded overlap still require an explicit backfill. Manual connections remain manual.