slobudget
SLO, error budget and burn-rate alert calculator for SRE teams. Define an SLO as YAML, feed it a metric export (Prometheus range-query JSON or CSV), and get the error budget, burn rates, exhaustion projection and compliance history, a replay of multi-window multi-burn-rate alerts over your history (with precision, recall, detection and reset times), plus ready-to-load Prometheus rules and a Grafana dashboard. It follows the method of the Google SRE Workbook chapter "Alerting on SLOs".
Features
- SLO spec as code: availability (good/total) and latency-threshold (histogram) SLIs, rolling or calendar (month/week) windows, custom alert policies.
- Inputs: Prometheus range-query JSON, CSV
timestamp,good,total, or a deterministic synthetic generator with three incidents. - Engine: exact window sums via prefix sums, error budget in minutes and percent, burn rate per window, exhaustion projection, compliance history.
- Alert replay: evaluates every policy at every tick and scores the alerts against budget-burning incidents found in the data.
- Generators: Prometheus recording and alerting rules, Grafana dashboard JSON, Markdown report.
- CLI:
report,simulate,rules,dashboard,whatif,generate.
Install
python3.12 -m venv .venv && .venv/bin/pip install -e '.[dev]'
Python 3.12+, dependencies: click, PyYAML.
Quickstart
slobudget report --slo examples/checkout-api.slo.yaml --data examples/synthetic-90d.csv
slobudget simulate --slo examples/checkout-api.slo.yaml --synthetic
slobudget rules --slo examples/checkout-api.slo.yaml -o slo-rules.yaml
slobudget dashboard --slo examples/checkout-api.slo.yaml -o dashboard.json
slobudget whatif --objective 99.95
Every data command takes exactly one of --data FILE (.json is read as Prometheus, anything else as CSV) or --synthetic.
SLO spec
service: checkout-api
name: availability
objective: 99.9
sli:
type: availability
good: 'http_requests_total{job="checkout-api",code!~"5.."}'
total: 'http_requests_total{job="checkout-api"}'
window:
type: rolling
days: 30
labels:
team: payments
sli.type: availabilityneedsgoodandtotalselectors.sli.type: latencytakeshistogram, optionallabelsandthreshold_seconds(good =_bucket{le="<threshold>"}, total =_count); the threshold must be an existing bucket boundary.window:{type: rolling, days: N}(or just30d), or{type: calendar, period: month|week}.alerting.policiesis optional. Default is the workbook set: 14.4x (1h/5m, page), 6x (6h/30m, page), 3x (1d/2h, ticket), 1x (3d/6h, ticket). A custom example is inexamples/search-latency.slo.yaml.
Input formats
- CSV: header
timestamp,good,total; timestamps are ISO 8601 or epoch seconds; each row is the event counts for the interval starting at the timestamp. - Prometheus: a
status: successmatrix response whose series carry a labelsli(orseries) ofgood,badortotal, or a__name__ending in those words. Values are per-step increases, e.g.sum(increase(http_requests_total{code!~"5.."}[5m]))exported withstep=300. Seeexamples/prom-export.json. slobudget generate [--days 90] [--step 300] [--seed 7] [--format csv|prom] -o FILEwrites the demo series used inexamples/.
Usage and real output
report
slobudget report --slo examples/checkout-api.slo.yaml --data examples/synthetic-90d.csv --history-days 30
Options: --at TIME (evaluate in the past), --history-days N, --with-simulation, --format markdown|json, -o FILE.
SLO report: checkout-api (availability)
Evaluated at 2026-09-29T00:00:00Z over window 30d (from 2026-08-30T00:00:00Z). Status: WITHIN BUDGET.
Summary
| Metric | Value |
|---|---|
| Objective | 99.9% |
| SLI | 99.9600% |
| Good / total events | 23,574,201 / 23,583,645 |
| Bad events | 9,444 |
Error budget
| Minutes | Share | |
|---|---|---|
| Total | 43.2 | 100.0% |
| Consumed | 17.3 | 40.0% |
| Remaining | 25.9 | 60.0% |
Burn rate
| Window | Burn rate |
|---|---|
| 5m | 0.00x |
| 30m | 0.00x |
| 1h | 0.26x |
| 2h | 0.21x |
| 6h | 0.21x |
| 1d | 0.23x |
| 3d | 0.23x |
| 30d | 0.40x |
Exhaustion projection: at the current 6h burn rate of 0.21x the remaining budget lasts 86d 6h 18m (until 2026-12-24T06:18:46Z).
Alerting policies
| Policy | Severity | Burn rate | Long / short | Budget burned at trigger | Budget gone in |
|---|---|---|---|---|---|
| page-fast | page | 14.4x | 1h / 5m | 2.0% | 2d 2h |
| page-slow | page | 6x | 6h / 30m | 5.0% | 5d |
| ticket-fast | ticket | 3x | 1d / 2h | 10.0% | 10d |
| ticket-slow | ticket | 1x | 3d / 6h | 10.0% | 30d |
Compliance history (every 30d)
| As of | SLI | Budget remaining | Met |
|---|---|---|---|
| 2026-07-31T00:00:00Z | 99.9639% | 63.9% | yes |
| 2026-08-30T00:00:00Z | 99.9674% | 67.4% | yes |
| 2026-09-29T00:00:00Z | 99.9600% | 60.0% | yes |
simulate
slobudget simulate --slo examples/checkout-api.slo.yaml --data examples/synthetic-90d.csv
Options: --eval-step SECONDS, --incident-burn X (burn rate that defines an incident, default 1), --incident-min-budget PCT (default 1).
Alert replay: checkout-api (availability)
Incidents (ground truth, budget-burning periods): 3
| # | Start | End | Duration | Bad events | Budget | Peak 1h burn |
|---|---|---|---|---|---|---|
| 1 | 2026-07-21T03:15:00Z | 2026-07-21T04:00:00Z | 45m | 3,078 | 13.0% | 229.4x |
| 2 | 2026-08-17T14:00:00Z | 2026-08-17T20:00:00Z | 6h | 2,440 | 10.3% | 12.9x |
| 3 | 2026-09-10T06:05:00Z | 2026-09-14T05:00:00Z | 3d 22h 55m | 4,794 | 20.2% | 1.9x |
Alerts that would have fired:
| Policy | Severity | Fired | Resolved | Duration | Peak long-window burn |
|---|---|---|---|---|---|
| page-fast | page | 2026-07-21T03:20:00Z | 2026-07-21T04:05:00Z | 45m | 229.4x |
| page-slow | page | 2026-07-21T03:25:00Z | 2026-07-21T04:30:00Z | 1h 5m | 37.1x |
| ticket-fast | ticket | 2026-07-21T03:40:00Z | 2026-07-21T06:00:00Z | 2h 20m | 5.3x |
| ticket-slow | ticket | 2026-07-21T03:45:00Z | 2026-07-21T10:00:00Z | 6h 15m | 1.6x |
| page-slow | page | 2026-08-17T16:55:00Z | 2026-08-17T20:20:00Z | 3h 25m | 12.2x |
| ticket-fast | ticket | 2026-08-17T18:15:00Z | 2026-08-17T21:40:00Z | 3h 25m | 4.1x |
| ticket-slow | ticket | 2026-08-17T18:20:00Z | 2026-08-18T01:50:00Z | 7h 30m | 1.3x |
| ticket-slow | ticket | 2026-09-12T05:00:00Z | 2026-09-14T07:30:00Z | 2d 2h 30m | 1.4x |
Detection quality (precision = alerts overlapping an incident; recall = incidents with an alert; detection = incident start to first alert; reset = incident end to alert resolve):
| Policy | Alerts | Precision | Recall | Mean detection | Mean reset |
|---|---|---|---|---|---|
| page-fast | 1 | 100% | 33% | 5m | 5m |
| page-slow | 2 | 100% | 67% | 1h 32m | 25m |
| ticket-fast | 2 | 100% | 67% | 2h 20m | 1h 50m |
| ticket-slow | 3 | 100% | 100% | 17h 15m | 4h 46m |
| all | 8 | 100% | 100% | 16h 38m | 4h 46m |
The three synthetic incidents are a 45 minute hard outage, a 6 hour 12x degradation and a four day 1.4x slow leak. Each policy catches what it is designed for: the fast page rule sees only the outage, the 6x rule also the degradation, and only the 1x ticket rule sees the slow leak.
rules
slobudget rules --slo examples/checkout-api.slo.yaml (alert group shown; the recording group defines slo:sli_error:ratio_rate<window> for every window)
- name: slobudget.checkout-api.availability.alerts
interval: 30s
rules:
- alert: CheckoutApiAvailabilityErrorBudgetBurnPageFast
expr: |-
slo:sli_error:ratio_rate1h{service="checkout-api",slo="availability"} > 0.0144
and
slo:sli_error:ratio_rate5m{service="checkout-api",slo="availability"} > 0.0144
labels:
service: checkout-api
slo: availability
team: payments
severity: page
long_window: 1h
short_window: 5m
annotations:
summary: checkout-api availability SLO is burning error budget at 14.4x
description: Error ratio exceeds 14.4x the budget rate over 1h and 5m. At this rate 2% of the 30d
error budget for a 99.9% objective is consumed in 1h.
- alert: CheckoutApiAvailabilityErrorBudgetBurnPageSlow
expr: |-
slo:sli_error:ratio_rate6h{service="checkout-api",slo="availability"} > 0.006
and
slo:sli_error:ratio_rate30m{service="checkout-api",slo="availability"} > 0.006
dashboard
slobudget dashboard --slo FILE -o dashboard.json produces a Grafana dashboard (import it and pick your Prometheus data source) with SLI and budget-remaining stats, an error budget burn-down, SLI over time and burn rate per window. It queries the recording rules, so load the output of rules first.
whatif
slobudget whatif --objective 99.95
Allowed downtime (error budget) by objective; * = requested
| Objective | 7d (min) | 28d (min) | 30d (min) | 90d (min) |
|---|---|---|---|---|
| 90% | 1,008 | 4,032 | 4,320 | 12,960 |
| 95% | 504 | 2,016 | 2,160 | 6,480 |
| 99% | 101 | 403 | 432 | 1,296 |
| 99.5% | 50.40 | 202 | 216 | 648 |
| 99.9% | 10.08 | 40.32 | 43.20 | 130 |
| 99.95% * | 5.04 | 20.16 | 21.60 | 64.80 |
| 99.99% | 1.01 | 4.03 | 4.32 | 12.96 |
| 99.999% | 0.10 | 0.40 | 0.43 | 1.30 |
Add --slo and --data/--synthetic to also evaluate your history against the alternative objective.
Configuration
There are no config files or environment variables; everything is in the SLO YAML and CLI flags. Errors in specs or data exit with status 1 and an error: message.
Architecture
| Module | Role |
|---|---|
slobudget/spec.py |
SLO YAML parsing and validation, durations, alert policies |
slobudget/series.py |
Series with prefix sums, CSV and Prometheus loaders and writers, synthetic generator |
slobudget/engine.py |
Window bounds, budget, burn rate, projection, history, incident detection, alert replay and scoring |
slobudget/rules.py |
Prometheus recording and alerting rules |
slobudget/dashboard.py |
Grafana dashboard |
slobudget/report.py |
Markdown and JSON rendering, what-if table |
slobudget/cli.py |
Click commands |
Algorithms and worked examples are in docs/methodology.md.
Tests
.venv/bin/pytest
The suite covers window arithmetic, the SRE workbook figures (2%, 5% and 10% budget at trigger), alert replay on synthetic incidents, PromQL sanity (a small tokenizer in tests/promql_lint.py), YAML/JSON validity and the CLI.
Limitations
- Generated rules and dashboards approximate calendar windows with 30d (month) or 7d (week) rolling windows; the report and simulation use true calendar bounds.
- Windows shorter than the data step are widened to one step.
- Incident ground truth is derived from the data (hourly buckets burning at 1x or more, at least 1% of the budget), so precision and recall are relative to that definition.
- Exhaustion projection assumes the 6h burn rate persists and ignores old errors rolling out of the window.
- A single SLO per spec file; counters must be pre-differenced into per-step increases.