TL;DR - An SLO without an error budget you actually spend is a number on a wiki, not a reliability practice. The error budget is the whole point: it is a pre-agreed trade between reliability and velocity, decided while everyone is calm, so that when the budget runs out the answer - stop shipping features, fix reliability - is already made. Almost nobody spends it. Teams set a target from ambition instead of user need (often a heroic 100%), measure the wrong thing (host uptime, not the user’s journey), page themselves at 3am on the raw threshold, and then blow through the budget without changing a single plan. This is the four moves that turn an SLO from decoration back into a decision, and the honest cases where you don’t need one at all.
I run reliability for a living, and I have read a lot of SLO documents. Most of them are beautiful. Four nines here, a p99 latency target there, a tidy little table with a green cell that says “compliant”. And almost every one of them is inert. The target exists, the dashboard exists, and if you ask the team “what happens when you blow it?” the honest answer is a shrug. Nothing happens. The number was never wired to a decision.
That is the failure I want to talk about, because it is the specific way SLOs fail, and it is different from the way DORA dashboards fail. A gamed DORA metric is a thermometer someone painted green. A dead SLO is worse: it is a contract nobody intends to honour. The error budget is the honouring mechanism, and if you are not spending it, you don’t have an SLO. You have a KPI wearing an SRE costume.
The error budget is the whole point
Start from what an SLO is actually for, because the industry has quietly forgotten.
A Service Level Objective is a target for how reliable a service should be - say, 99.9% of checkout requests succeed over 28 days. The inverse of that target is the interesting part. If you promise 99.9%, you have explicitly said the other 0.1% is allowed to fail. That 0.1% is your error budget: a quantity of unreliability you have decided, in advance, that you can afford to spend.
And spend is the right verb. An error budget is not a threshold you defend to the death. It is a currency you are supposed to use. When the budget is healthy - plenty left, nothing on fire - you should be shipping features fast, taking deploy risks, running the experiment that might break. When the budget is exhausted, you stop shipping features and you spend your engineering time buying reliability back. That is the entire mechanism: a pre-negotiated rule that converts a reliability number into a decision about what the team works on next.
This is why the SLO is genuinely powerful and not just another metric. It settles the oldest argument in engineering - “ship faster” versus “make it stable” - by turning it into a budget with a balance. Product doesn’t have to win that fight every quarter and neither does SRE. The number decides, because the number was agreed by both sides before anyone was angry.
Which means the test of a real SLO has nothing to do with the dashboard. It is this: has the error budget ever changed what your team did next? If a blown budget has never once paused a roadmap, moved an engineer onto reliability work, or killed a risky launch, then your SLO is doing no work at all. It is the number nobody spends. The rest of this post is the four ways teams end up there.
100% is the wrong target, and so is your gut
The first mistake happens before any code runs: the target gets picked from ambition instead of from what users need.
Someone in a room says “well, we can’t aim for downtime, can we? Let’s say 100%.” Or they reach for five nines because it sounds serious. Both are the same error. A target of 100% - or a target so high you can never actually reach it - has a fatal property: it leaves you no budget to spend. Every single blip is now a breach. Every deploy is a risk you can’t afford. You have built a system where the only rational move is to stop changing anything, which is exactly the frozen, nothing-moves failure mode reliability is supposed to prevent. A 100% target isn’t ambitious. It is a way to make reliability and velocity enemies again, permanently.
The right target comes from the other direction: how reliable does this service need to be for the people using it, and no more? Two questions get you most of the way there.
- What does the user actually notice? If checkout is down for 30 seconds and retries succeed, most users never know. If it is down for ten minutes at peak, you lose real money. The gap between those tells you where your target lives. You are pricing in the user’s tolerance, not your pride.
- What is the reliability of everything you depend on? If your payment provider offers 99.95%, promising 99.99% for checkout is a fantasy. You cannot be more reliable than your hard dependencies without heroics you can’t sustain.
The number you land on should have slack in it on purpose. 99.9% instead of 99.99% is not laziness; it is a deliberate decision to keep budget in the tank so you can spend it on shipping. The best SLO I ever set was one we lowered, because the old target was so high the team had quietly stopped deploying on Fridays, then Thursdays, then at all. Giving them budget back gave them their velocity back. The target existed to enable change, not to prevent it.
The budget nobody enforces
Say you picked a sane target. The second failure is the one that names this post: the budget runs out and nothing happens.
This is almost never a character flaw. It is a missing artefact. There is no error budget policy - the one-page document, agreed by engineering and product before the fire, that says what the team does when the budget is spent. Without it, “we’re over budget” is just an observation, and observations don’t reprioritise roadmaps. The person who wants to ship the feature is in the room and motivated; the abstract cost of unreliability is not. Feature wins, every time, and the budget becomes decoration.
A real policy is blunt and boring on purpose:
- While there is budget: teams ship at will. No reliability gate, no permission needed. The budget existing is the permission.
- When the budget is exhausted: feature work stops and reliability work takes priority until the service is back inside its objective. Not “we’ll be more careful” - a concrete freeze on new risk, with named work to buy the budget back.
- Who can invoke the brakes, and who can override. Usually the team owns it, with a documented, expensive escalation for the genuine “we ship this or we lose the customer” case. Overrides should be possible and rare, and every one gets written down.
Two things make this stick. First, it has to be agreed in advance - the entire value is that the argument was settled while everyone was calm, so the moment of stress just executes a decision instead of re-litigating one. Second, someone has to be willing to actually pull the brake once. The first time a team stops a roadmap because the budget is blown, the SLO becomes real to everyone watching. Until that happens, it is a suggestion. This is the same move as an architecture decision record applied to reliability: you write down the “no” and the conditions once, so you don’t re-argue it every incident.
And a blown budget is a gift to your incident practice, not a punishment. It is the loudest possible prompt to go find out why you spent it - which is only useful if your postmortems actually change something rather than generating a document and moving on. The budget tells you when to look; the review is how you learn. A team that blows its budget, runs an honest review, fixes the cause, and buys the budget back has just used the entire SRE toolkit exactly as designed.
You’re probably measuring the wrong nine
The third failure is subtler and more common than the first two combined: the SLO measures something real, just not the thing the user experiences.
The classic version is uptime of a host or a pod. Your monitoring says the instance responded to its health check 99.99% of the time, so you report 99.99% availability - while users were getting 500s from a downstream call the health check never touches. The number is true and useless. It measures whether your infrastructure was up, not whether your service worked. This is the exact distinction I keep coming back to in real observability versus a wall of green dashboards: the question is what the system did to the people using it, not what your tooling found convenient to record.
A good SLO is measured on a user journey, expressed as a Service Level Indicator - the actual signal you compute the objective from. Pick the handful of requests that carry the product’s value - “the checkout POST returns 2xx in under 800ms”, “the search query returns results in under a second”, “the login succeeds” - and measure the objective on those. Two rules that keep the indicator honest:
- Measure as close to the user as you can afford. At the load balancer is better than in the app; at the client is better still. Every layer you move away from the user is a layer where the number can be green while the user is suffering. The whole point of measuring on the journey is defeated if you measure it somewhere the journey doesn’t actually happen.
- Count what the user counts as failure. A request that returns a 200 with a broken body is a failure. A request that “succeeds” after a 40-second retry storm is a failure. If your indicator disagrees with the user about what a failure is, the user is right and your indicator is decoration.
And resist the urge to put an SLO on everything. One objective per microservice sounds rigorous and produces a wall of numbers nobody reads and nobody can act on - the reliability equivalent of paved-road sprawl. A few SLOs on the journeys that actually matter beat forty SLOs on things no user would notice. The point is decisions, and you can only make a decision about a number you are actually looking at.
Alert on the burn, not the level
The last failure turns a good SLO into a source of misery: paging on the raw threshold.
If you alert the moment availability dips below 99.9%, you have built a machine for waking people up over noise. A brief blip that spends a sliver of a 28-day budget is not an emergency, and treating it like one trains the team to ignore the pager - which is how the real outage gets missed. You have taken a strategic instrument and wired it to a smoke detector.
The mechanism that fixes this is burn rate: how fast you are spending the budget relative to the window. A slow burn that would exhaust the budget in three weeks is a ticket for Tuesday. A fast burn that would empty it in an hour is a wake-someone-up event. Alerting on burn rate, with a couple of thresholds for “urgent” versus “keep an eye on it”, means the pager fires in proportion to how much trouble you are actually in. The SLO stays a planning tool; the alerts become symptom-based and honest, the same discipline as paging on what users feel rather than on every twitch in a metric.
The subtle payoff: burn-rate alerting keeps the budget as a budget. Threshold alerting quietly converts it back into a line you must never cross, which drags you straight back to the 100%-target trap - defending the number instead of spending it. Burn rate lets a healthy service spend freely and only shouts when the spending is genuinely reckless. That is the number doing its job.
When you don’t need an SLO at all
The honest off-ramps, because SLOs are a tool with a scale and a cost, and below that scale they are ceremony.
- You have no users to disappoint yet. Pre-product-market-fit, the reliability that matters is “does the demo work”. An error budget policy for a service three people use is a governance ritual for a decision that doesn’t exist. Ship, find out if anyone wants it, and set an SLO when there is something to protect.
- The service is internal and low-stakes. The batch job that emails a weekly report does not need four nines and a burn-rate alert. “Someone notices within a day and fixes it” is a completely adequate reliability model. Reserve SLOs for the paths where unreliability actually costs something - money, trust, safety.
- You can’t act on the result. If the team that would own the SLO has no authority over the deploy pipeline, the dependencies, or the roadmap, an SLO just measures a weather system they can’t change. Fix the ownership first, or you are instrumenting helplessness.
- You’d be importing the machinery ahead of the scale. A full SLO-and-error-budget apparatus for a handful of services is the same category error as running Kubernetes for three of them: you have taken on the operating cost of a scale you don’t have. A shared understanding of “what counts as too broken” and a habit of fixing it beats a policy document nobody enforces.
You start earning SLOs when reliability becomes a recurring argument - when “should we ship or should we stabilise” keeps landing on the loudest person in the room, when the same service keeps hurting users and nobody can say whether that’s acceptable, when your platform team needs a way to offer reliability as a property teams can consume rather than a favour they request. That is exactly the problem the error budget solves, and it is worth every bit of the ceremony once you have it.
The bottom line
An SLO is not a number and it is not a dashboard. It is a decision you agreed to make before you had to make it: when the budget is healthy, ship; when it is spent, fix. Everything that makes SLOs valuable lives in that trade, and everything that makes them useless is a way of avoiding it - a target so high there is no budget, a policy nobody wrote so a blown budget changes nothing, an indicator measuring the host instead of the human, a pager that fires on the level instead of the burn.
So before you set your next four nines, ask the only question that matters: when we spend this budget, what will we actually do differently? If you can’t answer, you are not setting a reliability target. You are writing a wish on a wiki and calling it engineering. Pick a target with slack, measure it where the user lives, write down what a blown budget forces, and then - the hard part - spend it at least once. The first time the budget stops a roadmap is the moment your SLO becomes real.
If you’re standing up SLOs and want them to drive decisions instead of decorate a status page - or you’ve got a tidy table of green nines and a nagging sense that none of them has ever changed a plan - that’s the kind of problem I help teams untangle. Let’s talk.