Note / 003 · Reliability
Debugging production without guessing
A repeatable incident workflow for narrowing the problem, protecting evidence and restoring service safely.
- Published
- 2026-09-03
- Reading time
- 6 min read
Production debugging becomes dangerous when urgency replaces method. The fastest route to recovery is usually not trying more fixes—it is reducing uncertainty while preserving the evidence that explains what changed.
This workflow is designed for web applications and APIs, but the same reasoning applies to queues, workers and scheduled jobs.
Stabilize before investigating
First decide whether the incident is still getting worse. If users or data are at risk, reduce impact before searching for the perfect root cause.
Possible containment actions include disabling a feature flag, pausing a worker, rate-limiting an endpoint, routing traffic to healthy instances, or rolling back the last deployment. Choose the smallest reversible action that protects the system.
Write down the incident start time, affected user journeys and every mitigation. A short timeline prevents the team from repeating checks and gives later log searches a reliable time window.
Define the failure precisely
“The API is broken” is too broad to test. Replace it with a statement that can be disproved:
Requests to
POST /ordersin the production region return502for authenticated users, beginning around 14:10 UTC. Reads remain healthy.
A useful problem statement identifies:
- What operation fails and what still works
- Which environment, region, tenant or user group is affected
- The observed error or incorrect result
- When it began and whether the failure is constant or intermittent
Check recent change before deep theory
Look for changes near the start of the incident:
- Application or infrastructure deployments
- Database migrations and configuration updates
- Secret or certificate rotation
- Traffic shifts, scheduled jobs or unusual input volume
- Dependency or third-party service incidents
Correlation is not proof, but it provides high-value hypotheses. Compare a failing instance with a healthy one rather than reading one configuration in isolation.
Follow one request through the system
Choose a failed request and trace it across boundaries. A request or correlation ID is far more useful than searching every log for the word error.
edge request id
→ reverse proxy access log
→ application trace
→ database query or queue message
→ downstream response
At each hop, ask two questions: did the request arrive, and what happened before it left? The first missing or abnormal transition usually narrows the responsible layer.
Use all three observability signals together:
- Metrics reveal scope, timing and trends.
- Logs provide discrete events and local context.
- Traces connect work across services.
Separate symptoms from causes
A database timeout in an API log may be a symptom of exhausted connection pools, a slow query, network loss, lock contention or a downstream overload. Do not stop at the first visible exception.
Build a short hypothesis table:
Hypothesis Evidence for Evidence against Next safe test
Connection pool exhausted wait time increased reads still succeed inspect pool metrics
Bad release timing matches one old pod also fails compare config and traffic
Database overloaded CPU elevated replicas look normal inspect slow queries
Prefer tests that distinguish between several hypotheses without changing production state.
Change one variable at a time
Multiple simultaneous fixes destroy information. If scaling, restarting and changing configuration happen together, service may recover without revealing why—and the incident can return.
For every action, record:
- What you expect to change
- What metric or behavior will confirm it
- How long you will wait
- How to reverse the action
Restarts are sometimes valid containment, but capture logs, process state and relevant metrics first. Restarting too early often deletes the best evidence.
Verify recovery from the user's perspective
A green dashboard is not enough. Repeat the failed user journey, check error rates and latency, and watch the system for at least one meaningful traffic cycle.
Confirm that queues are draining, replicas are stable, retry traffic is not creating a second spike, and data written during the incident remains consistent.
Close the loop
After recovery, create a blameless record containing:
- Impact and duration
- Detection method and response timeline
- Technical root cause and contributing conditions
- What reduced or increased the impact
- Concrete follow-up work with owners and deadlines
The strongest follow-ups improve the system rather than reminding people to “be more careful”: an alert on pool saturation, a deployment guardrail, a tested rollback path, or a runbook for the same symptom.
The useful mental model
An incident is an information problem under time pressure. Protect users, narrow the failure, preserve evidence, test deliberately and verify recovery.
Speed comes from a repeatable process—not from guessing faster.