Lakshya

Infrastructure & Reliability · Reliability, operations & platforms · Chapter 6 of 33

Debugging that transfers

One method, applied to every resource. It turns troubleshooting from intuition into a checklist you can hand to someone else.

4 min read1 diagramAll 33 chapters

The most valuable skill in infrastructure is not knowing a particular system — it is having a method that works on a system you have never seen. The USE method is that: for every resource, check utilisation, saturation and errors.

THE SAME HOST, TWO MEASUREMENTS UTILISATION — what the dashboard shows 40% busy — “plenty of headroom” SATURATION — what users feel run queue: processes waiting for a CPU that is already taken 8 waiting — every request queues behind another Utilisation is an average. Saturation is the queue. Slowness lives in the queue. Measure utilisation, saturation and errors for every resource — the USE method — and check saturation first.
Utilisation is an average; saturation is the queue. A host at 40% CPU with eight processes waiting is saturated, and every dashboard will report it as idle. This single distinction resolves a large share of “it is slow but nothing looks wrong” investigations.

Applying it

ResourceUtilisationSaturationErrors
CPUpercent busyrun queue length, pressure stallthrottling
Memoryusedswapping, reclaim, OOM killsECC errors
Diskpercent busyqueue depth, awaitI/O errors, retries
Networkbits per secondinterface discardsCRC errors, drops

The column that matters is saturation, and it is the one almost never on the default dashboard.

Two habits worth more than any tool

  • Diff against a working comparator. If identical hosts exist and one is slow, mechanically compare everything — firmware, kernel parameters, negotiated link speed, memory population. The difference is nearly always in that diff, and finding it that way is much faster than reasoning about it.
  • Reason from the timing signature. Failing at a consistent elapsed time suggests something thermal or accumulating; failing at a consistent iteration suggests code; failing at a consistent time of day suggests a scheduled job or a neighbour.

Debugging production, when you did not write it

The production debugging skill is not knowledge of the system — you often have none — it is a search strategy that halves the space with each step, and a refusal to guess before the evidence supports it.

  • Start with the change log, not the code. Deploys, config flips, feature flags, dependency upgrades, certificate expiries, scheduled jobs, and traffic. A timestamp plus a deploy list resolves a large share of incidents before anyone opens an editor.
  • Establish the blast radius immediately. One user, one tenant, one region, one instance, or everyone? That single answer eliminates most hypotheses at once — a single-region failure is not a code bug, and a single-instance failure is not a deploy.
  • Work the request path in order — client, DNS, load balancer, gateway, service, dependency, datastore — and confirm each hop rather than assuming it. Most wasted incident time is spent debugging a layer that was fine.
  • Prefer evidence you can gather without a deploy. Logs, metrics, traces, a direct call to the service, a query against the datastore. Anything requiring a release adds twenty minutes and a risk.
  • Write the timeline as you go. Not for the postmortem — for you. Ten minutes into an incident nobody can remember what they have already ruled out, and the commonest waste is checking the same thing twice while the real cause sits unexamined.

Correlation, causation, and the deploy that was not the cause

The most common incident-response error is stopping at the first plausible correlation. A deploy went out at 14:15, the errors started at 14:20, so the deploy is the cause. Roll it back.

Often correct. And when it is wrong it is expensive, because the rollback appears to fix things — the real cause was a traffic pattern that also subsided — and the actual defect stays in the system with a false exoneration attached to it.

The cheap discipline: before accepting the correlation, ask what else changed in that window, and whether the failure mode is one this change could plausibly produce. A configuration change to a logging library is unlikely to cause a database timeout, however well the timestamps line up.

Roll back anyway. Restoring service is not the same as diagnosis, and it should not wait for one. But record that the diagnosis is unconfirmed, because a rollback that resolves the symptom is very often taken as proof and closes the investigation.

The signature of this error: the same incident recurring weeks later with a different deploy blamed.

Check yourself

What do you establish first in a production incident?What changed, and the blast radius — one user, one tenant, one region, one instance, or everyone. Each eliminates most hypotheses at once.
Why write a timeline during an incident?Because ten minutes in, nobody remembers what has been ruled out, and the commonest waste is re-checking the same thing.
Why is 'the deploy went out five minutes earlier' not a diagnosis?It is a correlation. Ask whether that change could plausibly produce this failure mode, and record that the diagnosis is unconfirmed even after a successful rollback.
What is the signature of a false diagnosis?The same incident recurring weeks later with a different deploy blamed.
← The physical layer, and why AI broke the datacentreRunning production →