Files
nexus/sreweekly/markdown/520/07-customers-over-control-how-we-measure-on-call-reliability.md
2026-09-12 17:23:01 +08:00

149 lines
13 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Customers over control: how we measure On-call reliability
- **期号**: SRE Weekly Issue #520(2026-06-07)
- **作者**: Mike Fisher — incident.io
- **链接**: https://incident.io/blog/customers-over-control
## 简介
I like the balance between ensuring 99.99% reliability and designing their product to encourage customers to use their platform in a way that effectively manages the 0.01% case.
> Reliability is a customer experience problem
## 正文
May 28, 2026 — 12 min read
Our On-call product has a lot of great features: configuring [escalation paths](https://docs.incident.io/on-call/escalation-paths#smart-escalation-paths), viewing [rotas and schedules](https://docs.incident.io/on-call/building-schedules#building-schedules), [requesting cover](https://docs.incident.io/on-call/responder-guide#3-request-cover-and-create-overrides), etc. However, when framing its reliability, we reduce it down to two critical pieces of functionality:
1. Ingesting [alerts](https://docs.incident.io/on-call/getting-started#4-creating-incidents-from-alerts) . An alert is a message we receive from a customer’s observability tooling to tell us that they think something is wrong and needs attention.
2. Sending timely [notifications](https://docs.incident.io/on-call/notifications) to on-call responders so that they can investigate.
It’s not that we’re happy if only these parts are working, but they are the most important parts.
In this post, I'll go into more detail on how we think about their reliability. Specifically, I want to talk about how we put *customers* at the centre of our reliability thinking. It’s easy to think about reliability from a purely technical perspective, especially for engineers. A customer-driven approach is in the DNA of incident.io, and hopefully I can use this post to show how it improves outcomes all round.
This post assumes knowledge of Service Level Objectives. The Google SRE book is the oft-cited bible, and their [intro](https://sre.google/sre-book/service-level-objectives/) is pretty good, but I find the rest of it quite a slog, so here’s the gist:
- **Service Level Indicator (SLI):** a quantitative measure of how the service is actually behaving (e.g. latency, error rate, availability) - the raw signal.
- **Service Level Objective (SLO)** : a target we set for an SLI internally (e.g. "99.9% availability over 30 days") - what "good" looks like.
- **Service Level Agreement (SLA)** : a formal, often contractual commitment to customers based on SLOs, with consequences (e.g. service credits) if we miss it.
We model the reliability of the On-call product using two SLIs that cover the two main functions above:
1. **Alert ingestion availability** : a classic HTTP API availability SLI; what proportion of requests we successfully process.
2. **Notification delivery latency <5m** : the proportion of notifications we dispatch “on time”.
Internally, we target a 99.99% monthly SLO for both, with an almost perfect record over the last 12 months:
Notifications were delayed in October 2025 by an AWS outage. We [learned from this and made improvements](https://incident.io/blog/service-disruption-october-20th-2025#on-call-notifications-were-delayed), and there’s more on this later in the post.
Our platform is architected with reliability at its core. This is a simplified diagram to illustrate my point - there are many more components, and all of them are replicated:
- We use a lightweight ingestion layer to durably write alerts to a queue (`web-alerts` ).
- An async system of message producers and subscribers then applies routing configuration and sends notifications, so we never drop work (`worker-on-call` ).
- All of this runs on dedicated infrastructure, isolated from the rest of the platform.
So far, this all seems pretty simple! However, we don’t have to poke at those SLI definitions much before we unearth some complexity.
I introduced this SLI as “a classic HTTP API availability SLI”:
```
1 - 5xx responses / total responses
```
We observe responses at the point closest to the customer that we can, which for us is a GCP load balancer. Requests have a few hops to make between the load balancer and our application layer, and we want to make sure the SLI covers all of that. If we misconfigure our load balancer and route requests to the wrong place, application-level metrics will show low error rates because there are no requests to return errors for!
We alert on per-request error rates at this layer and proactively investigate. That means whenever a transient network blip occurs, one of us wakes up and checks everything is OK. This happens very rarely and, in the vast majority of cases, a self-healing system quickly takes care of it.
There are multiple components covered by our alerting that we’re not directly in control of. For example, the load balancer and Kubernetes control plane are operated by GCP. Measuring and alerting like this has helped us identify and fix issues that are “outside” of our stack but that impact alert ingestion.
When we frame the reliability of alert ingestion, we don’t want to include this “noise” in the signal. What we actually measure is `good minutes / total minutes`:
1. Slice the month up into minutes.
2. Measure the error rate for each minute.
3. “Good” minutes have an error rate <10%.
This approach means that short-lived, self-healing blips are considered part of the norm. When the SLI is <100%, customers have been meaningfully impacted. It also encourages customers to ensure that their alert dispatching systems are designed with this level of fault tolerance in mind, for example, by using retries with backoff. We hold ourselves to a high standard, but this realistic view of complex systems is how we maximise our chances of ingesting alerts.
Now let's poke at notification delivery latency. We target dispatching notifications within 5 minutes of ingesting an alert — but when does the clock actually stop?
The easy answer: when we hand the notification off to a provider like Twilio or APNs. If they're degraded, that's not our fault. Right?
It’s easy to fall into debating “whose fault should this be” when thinking about dependencies between systems.
**We focus on customer experience — how do we make sure you get paged?**
For SMS and phone calls, we run two telecom providers active-active. If one can't dispatch, we try the other. This is exactly the gap we closed after missing our SLO in October 2025, when our sole telecom provider was caught up in the [AWS outage](https://incident.io/blog/service-disruption-october-20th-2025#on-call-notifications-were-delayed). (This gap was actually a known risk and we had work planned, but it bit us before we got to it.)
Some providers are monolithic — there's only one APNs API for iOS push notifications, so we can't run redundancy ourselves. Instead, the product nudges users to layer multiple notification methods (push *and* SMS *and* phone), so we always have another way to reach them.
So "dispatched on time" means **acknowledged by any provider within 5 minutes**. We own redundancy on our side; we encourage it on the customer's side. That combination is what makes a notification reliable.
Our notification delivery latency SLO measures the time it takes for a notification to be delivered from the moment an alert is ingested at the edge. However, our On-call product supports a bunch of different ways for customers to introduce “delay” into the escalation path:
- If something happens overnight, isn’t important enough to wake someone up, but does need looking at, you can [delay an escalation until working hours begin](https://docs.incident.io/on-call/escalation-paths#delay-escalation) .
- If you configure [alert grouping](https://docs.incident.io/alerts/escalations-from-alerts#grouping-alerts) , we’ll wait a little bit before notifying you, so that we have a window to check for duplicate alerts. This allows us to only notify a user once when many alerts come in for the same reason.
My favourite - users can define delays in their [notification rules](https://docs.incident.io/on-call/notifications#on-call-notifications-and-preferences). Here are mine:
1. Whenever I’m being paged, I immediately get a push notification and SMS. Having two methods gives me some redundancy. I get notified on my smartwatch, which has a good chance of waking me up, and a low chance of waking my wife up.
2. After 2 minutes I get a phone call. This is another layer of redundancy, both in notification methods, and for if I accidentally go back to sleep after the first round of notifications. This has a high chance of waking me up properly, but will also probably wake up my wife.
Being able to layer up notification methods based on how “disruptive” they are is a really useful tool. It adds up to a significant quality of life improvement in my house over a week of being on call!
From the moment an alert is ingested, [incident.io](https://incident.io) owes me some notifications immediately, and some a few minutes later (redundancy is the exception, not the rule). If there’s something wrong with our system and notifications are delayed, it’s easy to detect against the immediate notifications. It’s tricky for us to measure the latency of any that include intentional delay - it’s been intentionally latent. The system hasn’t been designed to be observed in this way.
The simplest option here would be to say that we only care about the reliability of “immediate” notifications. They’re the ones that matter most, right? My notification settings are cute, but I should be getting up when I receive the first one; the rest is on me.
We disagree! In the previous section we covered the best practice of having multiple notification methods set up for redundancy. This “retry with backoff” approach is another form of redundancy that we encourage. If my watch doesn’t wake me up, and I don’t get my phone call until 20 minutes later due to an issue in incident.io’s notification systems, and now things are really on fire, that’s not good enough.
The excuse that this is hard for us to measure doesn’t pass the “red face test”. We’d be embarrassed to tell a customer that a delayed notification wasn’t our fault, because *they* introduced a delay, when we’re the ones that told them that this is best practice!
Calculating notification delivery latency then looks like:
1. Pick a start time - usually when an alert is ingested, but there’s other cases like manual escalations.
2. Pick an end time - the first time we get an acknowledgement from any of our notification providers.
3. Calculate “configured delays” - sum up all the different ways you could have delayed the notification on purpose (there’s a lot and it’s some truly spectacular BigQuery SQL).
4. `latency = end time - start time - configured delays`
Any time between start and end that wasn’t intentionally introduced is our processing time and should be as fast as possible.
Instead of thinking about reliability as an exercise in figuring out what we can control, and ignoring anything beyond that, we think about what we'll be really proud to offer to customers.
In all three scenarios above, this produces the best outcomes:
- Instead of focussing on our API being “up”, we instead have to think about maximising the chance an alert is received and ingested successfully.
- Instead of saying “that’s not in our control” when a third-party dependency is degraded, we instead proactively assume they will go down, and design a system specifically to cope with it.
- Instead of saying “ugh, that’s going to be really hard to measure”, we embrace the complexity, deliver a better experience, and ensure our customers don’t have to pay the price.
In a world of metrics and uptime graphs, it’s easy to get sucked into narrowly measuring whether an individual component is ”up”, and forget that it’s a key part of a customer experience.
Customer outcomes matter more than any individual piece of the machine, and we aim to always build and measure our platform with that in mind.
Mike Fisher
Product Engineer
Today we're launching Investigations: agentic root cause analysis that starts the moment you're paged, figures out what broke and why, and works with your team through to resolution. Here's what we built, what's powering it, and why it took some time to get right.
Pete Hamilton
August 5, 2026
PagerDuty published a new comparison table about incident.io. Once again, it describes a product we don't recognize. So once again, we're correcting the record, row by row, with receipts.
Tom Wentworth
July 28, 2026
Today, we're launching the Opsgenie Rescue Program to make that landing soft: simplified migration and free overlap so you never pay two vendors at once.
July 9, 2026
Ready for modern incident management? Book a call with one of our experts today.
- All-in-one incident management
- Our unmatched speed of deployment
- Why we’re loved by users and easily adopted
- How we work for the whole organization