How to Find the Root Cause of Application Errors Faster

At 14:12, an application's error rate starts climbing.

The first dashboard shows a rise in failed checkout requests. Infrastructure appears healthy, database CPU is normal and the payment provider's status page reports no incident. Engineering opens the logs and finds hundreds of exceptions, but several different services are producing them.

Twenty minutes later, the team has plenty of data and very little understanding.

This is where root-cause investigations often become slow. The problem is not always a lack of information; it is the lack of a disciplined way to narrow that information.

The fastest investigations tend to move in the opposite direction from random debugging. They define the exact symptom, determine who and what is affected, establish when the behaviour changed, compare failing requests with healthy ones, and test increasingly specific explanations until the failure mechanism becomes clear.

Google SRE describes effective troubleshooting as an iterative process: start with observations, form hypotheses about possible causes, and test those hypotheses against the system rather than changing things at random. Google SRE: Effective Troubleshooting

For Levelworks, this is where Observable and Explainable & Debuggable App Health become practical. An application is easier to maintain when it not only reveals that an error occurred, but gives engineers enough evidence to work backwards toward why.

Start by describing the error precisely

“Checkout is broken” is not a useful diagnostic starting point.

Neither is:

“Users are seeing errors.”

Before investigating the cause, establish the symptom in enough detail that the team knows what it is trying to explain.

For example:

Since 14:12, approximately 8% of checkout requests using one payment route are returning HTTP 500 after 4–6 seconds. Other payment routes appear unaffected.

That statement immediately narrows the search.

Useful questions include:

  • When did the behaviour begin?
  • Which operation is failing?
  • What percentage of requests is affected?
  • Is the problem continuous or intermittent?
  • Which users, accounts, regions or application versions are affected?
  • Does the error occur in one service or across several?
  • Is the application failing completely, or merely getting slower?
  • What still works normally?

The last question is particularly important.

Healthy behaviour provides a control group.

If checkout fails only for one payment provider, the investigation should look very different from a situation where every checkout method fails.

Separate the symptom from the cause

An error message often describes where the failure surfaced, not where it originated.

Suppose the checkout API returns:

500 Internal Server Error

The immediate application log might show:

Order creation failed

Further investigation reveals that the order service timed out while requesting inventory. The inventory service was waiting for a database connection because its connection pool had been exhausted after a configuration change.

Which one is the root cause?

The HTTP 500 is the symptom.

The order-service failure is another symptom further inside the system.

The inventory timeout describes the failure mechanism more closely.

The configuration change may be the trigger.

The reason one configuration mistake could exhaust the entire pool might reveal another contributing weakness in design or validation.

Google's postmortem practice explicitly distinguishes an incident's trigger from its root cause, which is useful because production failures often involve several conditions rather than one neat explanation. Google SRE: Postmortem Analysis

Do not stop at the first technically correct explanation.

Ask:

What created the condition that produced this error?

If users are being affected, mitigate before pursuing perfect diagnosis

Finding the root cause matters, but it is not always the first operational priority.

If a production error is actively preventing customers from using an important function, restore service where possible while preserving enough evidence for deeper investigation.

That might mean:

  • rolling back a recent release;
  • disabling a problematic feature;
  • routing around a failing dependency;
  • reducing load;
  • reverting a configuration;
  • switching to a known-good component.

Google's incident-management guidance separates mitigation from longer-term remediation for exactly this reason: teams need to reduce user impact while continuing to understand the incident and prevent recurrence. Google SRE: Incident Management Guide

There is one important caution.

Do not destroy the evidence while mitigating the problem.

If restarting a service clears the condition, capture relevant logs, traces, resource information and configuration before the restart where practical. Otherwise the application may recover while the team loses its best chance to discover why it failed.

Establish the blast radius

One of the quickest ways to narrow root-cause analysis is to determine what is not affected.

Suppose reports are failing.

Check whether the problem affects:

  • every customer or a subset;
  • every report type or one;
  • every environment or production only;
  • every application version or the latest one;
  • every region or one location;
  • every database shard or one;
  • every request or only high-volume accounts.

This turns a broad investigation into a comparison problem.

If only customers above a certain data volume are affected, investigate what changes with dataset size.

If only one region fails, global application code becomes a less convincing explanation than regional infrastructure, configuration or dependencies.

If the previous application version is healthy while the new one fails, recent code or configuration deserves immediate attention.

AWS's current application-monitoring tooling follows this general diagnostic pattern by allowing teams to segment transaction spans and identify the operations, customers or dependencies associated with unusual latency and failures. AWS CloudWatch: Troubleshooting Application Issues

A useful troubleshooting habit is:

Compare failing population vs healthy population.

Differences between them are often more informative than examining the failing case alone.

Build a timeline before building theories

Production errors are frequently related to something that changed.

Create a short timeline around the beginning of the incident.

Include:

  • deployments;
  • configuration updates;
  • feature-flag changes;
  • database migrations;
  • dependency releases;
  • infrastructure changes;
  • unusual traffic;
  • credential rotations;
  • provider incidents.

Do not automatically assume the nearest change caused the error.

Timing is evidence, not proof.

But it is strong enough to investigate early.

Suppose errors begin at 14:12 and a configuration rollout completed at 14:09. Compare instances or requests using the old configuration with those using the new one. If both fail identically, the hypothesis weakens. If only the new configuration fails, it strengthens considerably.

The important discipline is to test the correlation, rather than simply declaring “the deploy caused it.”

This is faster and safer than repeatedly rolling things back because a change happened recently.

Use metrics to decide where to look

Metrics are most useful at the beginning of root-cause analysis because they show the shape of the problem.

Ask whether the error coincided with changes in:

  • latency;
  • throughput;
  • resource saturation;
  • queue depth;
  • connection usage;
  • dependency failures;
  • business-workflow success.

Suppose application errors increase at the same moment database connection utilisation jumps toward its limit.

That does not prove the database is responsible, but it produces a concrete hypothesis worth testing.

If application errors increase while database, infrastructure and dependency metrics remain entirely stable, you can direct attention elsewhere.

AWS's Well-Architected guidance recommends collecting application metrics, logs and traces specifically because these different forms of telemetry make troubleshooting and anomaly investigation more effective. AWS Well-Architected: Implement Application Telemetry

Metrics are not usually the root cause.

They help determine where the investigation should go next.

[Internal Link: “Logs, Metrics and Traces: The Foundations of Application Observability”]

Follow one failing request through the system

Aggregated metrics tell you something is wrong across many requests.

A representative failing request shows how the failure actually unfolds.

In a distributed application, start with one transaction that exhibits the problem and follow its path across services.

A checkout trace might look like:

POST /checkout                       5,240 ms

 ├── authenticate                       42 ms

 ├── create-order                       81 ms

 ├── reserve-inventory               5,004 ms

 │    └── database.connection        4,890 ms [ERROR]

 └── payment                         not called

The investigation has now moved significantly closer to the cause.

Checkout itself is not necessarily the problem.

Neither is payment.

The abnormal time sits inside inventory, specifically around database connectivity.

Google Cloud illustrates this exact investigative approach in its guidance on using traces and logs together for root-cause analysis: a trace identifies the problematic service or operation, then correlated logs provide the lower-level evidence needed to understand why it failed. Google Cloud: Using Traces and Logs for Root-Cause Analysis

Without distributed tracing, engineers often attempt to reconstruct this journey manually from timestamps across several log stores.

That is possible.

It is also much slower.

Correlate logs around the same execution context

Once the trace or failing component has narrowed the investigation, inspect the relevant logs.

The key word is relevant.

Searching every ERROR entry across production during a busy incident produces noise. Instead, use shared context such as:

  • trace ID;
  • request ID;
  • transaction ID;
  • operation;
  • service;
  • application version;
  • customer or tenant identifier where safe;
  • dependency;
  • error category.

OpenTelemetry's context-propagation model allows trace identifiers to move across service boundaries and be included in related telemetry. This means logs generated by several components during the same request can be connected without relying only on timestamps. OpenTelemetry: Context Propagation

A useful workflow might be:

error-rate spike → failing request → trace → failing span → logs from that execution

rather than:

error-rate spike → search millions of log lines

This is one of the clearest ways good observability reduces diagnosis time.

[Internal Link: “How Better Logging Makes Apps Easier to Maintain”]

Compare a failing request with a successful one

When an error is intermittent, one of the strongest diagnostic techniques is to place a failing transaction beside a successful transaction and ask what differs.

Compare:

  • service path;
  • application version;
  • input characteristics;
  • dependency response;
  • account type;
  • region;
  • feature flags;
  • database shard;
  • execution time;
  • configuration;
  • request size.

Suppose both checkout traces are identical until the inventory step.

The healthy request gets a database connection in 12 ms.

The failing request waits 5 seconds and times out.

That difference focuses the investigation far more effectively than examining the entire checkout implementation.

Google Cloud recommends a similar narrowing approach when troubleshooting latency: first determine whether the problem affects all requests or a small percentage, then identify individual high-latency requests for deeper trace or log analysis. Google Cloud: Troubleshoot Application Errors and Latency

Healthy requests show what the system looks like when it works.

Failing requests show what changed.

Turn observations into hypotheses you can disprove

A good investigation narrows explanations rather than collecting endless information.

Suppose you know:

  • errors affect only large accounts;
  • failures began before the latest release;
  • the application service is healthy;
  • slow traces concentrate around one database query;
  • successful smaller accounts execute the same query quickly.

Possible hypotheses might be:

  1. large accounts generate a much larger query result;
  2. one index is ineffective at higher data volumes;
  3. database locking affects accounts with more concurrent activity;
  4. query execution is exhausting a resource at a particular scale.

Now test them.

Inspect query plans. Compare data sizes. Check lock behaviour. Reproduce using representative production-like data.

Google SRE's troubleshooting methodology treats this as a hypothetico-deductive process: observations produce hypotheses, and investigations test predictions that would be true if those hypotheses were correct.

This approach is faster than trying plausible fixes one after another.

If you make several changes simultaneously and the error disappears, you may restore service without learning what actually caused the problem.

Change one variable at a time where possible

During difficult investigations, teams often make several changes at once:

  • restart the service;
  • increase memory;
  • increase database connections;
  • rollback the release;
  • disable one feature.

The system improves.

Nobody knows which action mattered.

That makes the root cause difficult to confirm and increases the chance that the same problem returns.

Where impact and safety allow it, change one relevant condition and observe the result.

For example:

Hypothesis: version 4.2 introduced the error.

Test: route representative traffic back to 4.1 while keeping infrastructure and configuration unchanged.

Hypothesis: one dependency causes the latency.

Test: compare traces using that provider with transactions that bypass it.

Hypothesis: database connection pressure causes the failures.

Test: correlate failure probability with connection-wait time and reproduce under controlled load.

Production incidents will not always permit perfect experiments.

The principle is still valuable: preserve enough control over variables that the result actually tells you something.

Reproduce the failure—but reproduce the right conditions

Reproduction remains extremely useful because it turns an intermittent production mystery into something engineers can examine repeatedly.

The danger is building a reproduction that is too clean.

An error affecting accounts containing millions of records may not appear in a developer database containing 500 rows. A concurrency problem may never occur with one test user, while a timeout involving an external provider may disappear when the provider is mocked.

Google Cloud's troubleshooting guidance uses a structured sequence of gathering details, mitigating impact, reproducing the problem and then performing root-cause analysis. It also notes that some failures may need to be reproduced in test or local environments where production reproduction would create unsafe side effects. Google Cloud: Local Troubleshooting Workflow

Good reproduction means preserving the characteristics that matter:

  • realistic data volume;
  • relevant configuration;
  • application version;
  • concurrency;
  • dependency behaviour;
  • request shape;
  • timing.

If changing one of those characteristics makes the error disappear, you have learned something useful.

Do not confuse correlation with causation

Production systems generate coincidences constantly.

CPU may increase at the same time as errors simply because both respond to higher traffic.

A dependency warning can appear during an incident without being responsible for it.

A deployment five minutes before failure is suspicious but not automatically guilty.

Before declaring a root cause, ask:

Does the proposed cause explain all the important observations?

Can we demonstrate the mechanism connecting it to the failure?

Does removing or correcting it eliminate the problem?

Does the explanation account for why some requests succeeded while others failed?

The best root-cause explanations have predictive power.

If you claim a database connection limit caused failures, you should be able to explain when connections reached the limit, why those requests timed out and why reducing the pressure or changing the limit altered the behaviour.

Watch for multiple contributing causes

Complex application failures rarely respect neat diagrams.

Suppose a release increases the number of database queries per request by 20%. Under ordinary traffic, nothing happens.

Then a marketing campaign doubles traffic.

Database connections become saturated.

Retry logic reacts by generating additional calls, increasing pressure further.

Eventually checkout fails.

What is the root cause?

“The release” is incomplete.

“High traffic” is incomplete.

“Database saturation” describes the failure condition but not necessarily why it became possible.

A useful investigation might record:

  • Trigger: unusually high traffic;
  • Failure mechanism: connection-pool saturation;
  • Contributing factor: increased query volume introduced in the recent release;
  • Amplifier: aggressive retry behaviour;
  • System weakness: inadequate capacity alerting or load testing.

This is much more useful for maintenance than forcing every incident into a single root-cause field.

Google's postmortem guidance encourages teams to examine the broader conditions around incidents rather than stopping after identifying one immediate technical failure.

Avoid five common root-cause investigation traps

Trap

Why it slows diagnosis

Better approach

Starting with every available log

Creates enormous search space

Define the failing operation and time window first

Blaming the latest deployment immediately

Timing alone does not prove causation

Compare old vs new behaviour

Changing several things at once

You cannot tell which change mattered

Test one strong hypothesis where possible

Investigating only the component throwing the error

Failures often originate upstream or downstream

Follow the complete request path

Stopping when service recovers

Symptom disappears but underlying weakness remains

Preserve evidence and complete the analysis

The common theme is uncontrolled search.

Fast debugging is mostly about shrinking the search space without discarding relevant evidence.

Capture what made the investigation difficult

After the cause is understood, ask one additional question:

Why did it take as long as it did to find?

Perhaps logs did not contain request IDs.

Maybe tracing stopped at an external dependency, a dashboard aggregated every error into one metric, or nobody knew a configuration change had been deployed.

Those are valuable findings because they can make the next investigation faster.

Google's incident-management guidance recommends examining not just the technical cause but also detection, mitigation, coordination and other aspects of the response that could be improved.

If every production incident requires engineers to add temporary logging before they can understand the application, that is not merely an inconvenience.

It indicates weak Explainable & Debuggable health.

Turn the root cause into protection against recurrence

Root-cause analysis should finish with more than a corrected line of code.

Depending on what was learned, the follow-up might include:

  • a regression test;
  • better input validation;
  • improved timeout or retry behaviour;
  • a capacity alert;
  • stronger logging;
  • additional tracing;
  • a safer configuration check;
  • revised deployment controls;
  • documentation of an operational dependency.

The objective is to change the system so the same class of failure becomes less likely—or much easier to detect and diagnose.

Google's SRE incident philosophy places strong emphasis on learning from failures specifically because recurring incidents create operational toil and repeatedly consume engineering effort.

[Internal Link: “Why the Same Bugs Keep Coming Back and How to Stop Them”]

Faster root-cause analysis comes from narrowing uncertainty

Teams do not find root causes faster simply by collecting more data.

They get faster by asking better questions in a better order.

Define the exact symptom. Establish the blast radius. Build the timeline. Look for meaningful changes. Use metrics to locate abnormal behaviour, then inspect representative failing requests. Follow those requests across service boundaries, correlate their logs, compare them with healthy transactions and test specific

‍

Continue Reading