· 7 min read
Alert on Impact, Not Existence.
A vendor incident is not an event. A vendor incident that touches your dependency graph is. Why we build alerting, measurement, and SLA money math around that distinction.
By CheckUpstream Team
Alert on Impact, Not Existence.
Here is a claim that sounds obvious and is almost universally unimplemented: a vendor incident is not an event. A vendor incident that touches your dependency graph is an event. Everything else is weather.
Most monitoring tools disagree with this claim by design. They compete on how many status pages they watch and how fast they can relay a change. The result is a product category that converts other people's incidents into your notifications, at a rate limited only by how much of the internet is broken today. Teams respond the only way they can: they mute the channel. Then a vendor they actually depend on goes down, the alert lands in the muted channel, and the tool has failed at the one moment it existed for.
This is usually diagnosed as alert fatigue, as if the problem were volume. It isn't. It's scoping. An alert about a service you don't use isn't a slightly-less-relevant alert. It's noise wearing an alert's clothing, and every one of them teaches your team that the channel lies.
We build CheckUpstream around four rules that follow from taking the opening claim seriously. This post is those rules, argued in public, with the actual mechanics behind them — including the places where we're not finished.
Rule 1: No alert without a name attached.
The test we apply to every alert before it ships: does it name what of yours is affected? If it can't, it doesn't page.
Answering that question requires knowing your stack, so that's where the product starts — not with a list of services you tick boxes against, but with your repositories. We parse your dependency manifests — package.json, requirements.txt, go.mod, Cargo.toml, Terraform, docker-compose, and the rest — and map packages to the upstream services behind them, down to the sub-service where it matters. @aws-sdk/client-s3 is not "AWS", it's S3. A Workers AI binding calling @cf/baai/bge-m3 is not "Cloudflare", it's one model on one product. A checkbox list goes stale the sprint after someone fills it in; your lockfile can't.
That graph is what makes scoping possible. When an incident is confirmed, we score it against every project in your org. The alert that fires carries the verdict: which projects, through which dependencies, at what severity. When the Cloudflare Workers AI brownout of 2025-11-04 came through, the fan-out analyzer's verdict across customer projects with a Workers AI dependency read: 17 degraded, 41 operational, 3 down. That per-project verdict — not "Cloudflare went yellow" — is the alert.
The suppression is as load-bearing as the alert. When your project topology exists and an incident scores zero impact against it, we suppress the page below a severity floor instead of forwarding it. Today that floor defaults to major outages: a vendor's partial outage that your graph says can't touch you stays out of your pager, while a full-scale major still gets through even on a zero score, because graphs can be wrong and majors are where being wrong is expensive. Two more deterministic gates back this up: an incident we detected from community or feed signal never pages off a single uncorroborated source, and a status page flapping open-resolved-open won't re-page you about the same service inside a 30-minute window.
Honesty requires saying where this stops today. Impact scoring, the suppression floor, and the noise gates are live. Fully impact-only alerting — where anything outside your graph is silence by default, at every severity — is the direction we're building toward, not yet the default every org experiences. Existing orgs keep their configured behavior; the floor is overridable per org. We'd rather describe the machine as it is than as the diagram says it will be.
Rule 2: Measured, not claimed.
There's a second failure hiding inside status-page relays, worse than the scoping one: the source material under-reports.
Status pages are communications channels, not instruments. They post after internal confirmation, after severity classification, after someone approves the wording. We wrote up the structural version of this argument in Status Pages Lie; the measured version is in the Workers AI teardown, where of 22 Workers AI-scoped incidents our engine tracked in 2025, eleven never rolled up to a full-service Cloudflare status banner at all. Narrow sub-service brownouts — the incidents most likely to hit a specific dependency of yours — are precisely the ones least likely to be acknowledged.
So we treat the vendor's word as one input among five. Our engine classifies every signal source into one of five independent classes: vendor self-report (status pages, RSS), customer telemetry (SDK measurements from real production traffic), community signal (Hacker News, Reddit, Bluesky, GitHub issue velocity), network health (Cloudflare Radar), and synthetic probes (our own active measurements). Before we'll confirm an incident the vendor hasn't acknowledged, the composite score has to cross 0.6 with agreement from at least two distinct classes — fifteen Reddit posts are still one class, and one AI-parsed RSS entry is never enough to page anyone. Signal contributions decay with a 30-minute half-life, so stale corroboration doesn't prop up a dead incident.
The principle generalizes past incident detection: no number we publish is invented or extrapolated for effect. Every figure is a query against our own measurements, a value from your systems, or a vendor's published term. If we can't name the measurement behind a number, the number doesn't ship.
Rule 3: Deterministic where money moves.
When a vendor misses its published SLA, you're owed credits — but only on what you can prove, filed in the vendor's format, inside the vendor's window. This is the part of the product where a wrong number isn't embarrassing, it's a false financial claim. So the money path contains no model anywhere.
The refund derivation is a pure function: measured probes, plus the vendor's published SLA rules, plus the billing window in, refund-window candidates out. Same inputs, bit-identical outputs, every run — no clock reads, no randomness, no I/O inside the computation. The algorithm is versioned, and a replay job re-derives past windows against stored inputs to catch any divergence within a version.
That reproducibility is not academic; it's how we caught our own worst bug. An early version of the deriver stored a credit percentage in a field that rendered as dollars — a 10% credit displayed as $10 regardless of what you actually spent. Because every derivation is versioned and replayable, the fix was a new version that prices credits against your real vendor spend or shows nothing, plus a documented history that still tells you exactly what the old rows meant. An AI-generated claim estimate could never have been audited that way, which is exactly why there isn't one.
The same terms feed our public per-vendor claim guides: the published uptime targets, the credit ladder, the evidence the vendor requires, the filing channel, and the filing deadline, restated as steps. No generated prose in the path — every sentence restates a tracked term. Your finance team can check the math against the vendor's own SLA page, and they should.
Rule 4: Every detection ends in an action.
A dashboard nobody acts on is a failure state, however accurate it is. So we hold every detection to a simple standard: it must terminate in one of three things.
A named impact. An alert that says which projects are affected, through which dependencies — plus the measured error-rate and latency deltas when your own SDK telemetry saw the incident before the vendor admitted it — so the on-call engineer's first move is communication and fallback, not investigation.
A suppressed non-event. The incident that scored zero against your graph and never paged you. This is the invisible product. It still exists as a row — on the dashboard, in the public feed, in the SLA math — it just didn't cost anyone attention.
A filed claim. Downtime crossed a published SLA threshold, the evidence is assembled, the deadline is tracked, and the claim is ready to submit through the vendor's actual channel.
Impact, silence, or money. If a feature can't end in one of those, we don't build it.
The bet.
The monitoring industry's bet has been that more coverage and faster relays make a better product. Our bet is that the unit of value was never the incident — it's the intersection of the incident with your stack, measured independently because vendors under-report, priced deterministically because money needs audit trails, and delivered as something you act on.
A vendor incident is not an event. Yours is.