HIVE80lab — Ops notes

The four golden signals: what to watch when you can only watch four things

Most small teams' monitoring grows the same way: one panel per alert, one alert per scare, until the dashboard is forty panels deep and nobody can say what a healthy service looks like. The four golden signals — latency, traffic, errors, saturation — are the opposite bet: four numbers, one row each, that will notice nearly every real outage before a customer does. This page is the minimum-viable monitoring contract; the SLO definition turns two of the signals into a target, the burn-rate alerts turn the error signal into a pace, and the paging policy decides who gets woken when a row goes red.

The reason four works: every user-visible symptom is one of four sentences — it's slow (latency), nobody's using it (traffic), it's broken (errors), it's about to be (saturation). Panels that don't answer one of those four sentences are decoration.

1. The four signals, one line each

2. The traps each signal hides

Averaged latency. A mean can sit flat while the p99 is on fire — 1% of users having a terrible time does not move an average, but it fills a support inbox. Percentile lines only.

Status-code error counting. If errors are “HTTP 5xx,” every 200-wrapped failure is invisible: the payment endpoint that returns 200 with {"status":"failed"}, the import that half-completes. Count business-level failures as errors too — one counter per known silent-failure mode.

Reading signals alone. “Errors up 100%” means nothing without traffic: if demand doubled, the error rate is flat. Every alert text should carry the ratio (“error rate 0.8% vs 0.3% baseline”), not the raw count.

Saturating the wrong resource. Teams watch CPU because it is on every dashboard by default, then die by connection-pool exhaustion, disk inode exhaustion, or queue backlog. Ask once, per service: what runs out first? That is the saturation metric — and if you cannot name it, you do not know your own ceiling.

Zero traffic is not quiet health. A service receiving no traffic is a dead service or a broken upstream. Alert on traffic collapse as well as load: traffic < 20% of same-hour baseline pages just like an error spike.

3. Page or ticket: thresholds per signal

Map each of the four rows to a response class using the four-question page test — the defaults that work for most small teams:

Alert text carries the arithmetic, same rule as everywhere: “DB pool 94% full, p99 1.9s vs 480ms baseline, climbing 6%/min — runbook: db-pool-exhaustion.md.”

4. The wiring checklist (one afternoon)

5. Worked example

A nine-person payments SaaS runs exactly four rows on its checkout service. Friday 17:40, the saturation row — DB connection pool — climbs past 90% while latency is still inside its alert line; the pool alert pages with the projection. On-call restarts a wedged worker at 17:52; p99 recovers by 18:05; total customer impact is one minute of slow checkouts that never reached the error line. The post-mortem is four sentences and one dashboard tweak: the pool counter also became a burn-rate input, because the pool had been draining for two hours before anyone looked.

The counter-example is the same Friday at a team with a forty-panel dashboard, all averages: the pool exhaustion is invisible (panel 31, “worker CPU,” reads a comfortable 30%), latency panels show the mean absorbing the tail, and the first error-rate alert waits for hard 5xx — which start at 18:20 when the pool is fully dead. Detection came from a customer's Slack message, recovery took 3 hours, and the Monday retro produces a forty-first panel instead of a threshold decision.

6. Metrics

From the HIVE80lab kit

Related: the SLO definition template turns the latency and error rows into a target, the burn-rate alerts give the error row its pace thresholds, and the paging policy decides which of the four rows is allowed to wake a human.