← Back to Insights

Recurring engineering effort

Root Causes Behind Repeat Incidents

Written by:Better SoftwareBetter Software TeamUpdated 6 min read
Root Causes Behind Repeat Incidents

Quick Answer

Recurring incidents usually trace back to incomplete or localized fixes, missing monitoring for specific failure modes, fragile architecture, thin testing against known failure conditions and weak operational processes. Finding the pattern means collecting incidents over a defined period, grouping similar ones, scrutinizing post-mortems, correlating with changes, and categorizing root causes before funding systemic remediation that goes beyond the visible symptom.

Recurring incidents most often result from:

  • Incomplete or localized fixes that fail to address the systemic issue.
  • Lack of proper monitoring or alerting for specific failure modes.
  • Architectural choices introducing inherent fragility.
  • Insufficient testing against known failure conditions.
  • Operational process deficiencies.

Thorough post-incident analysis is crucial for identifying these patterns.

Why This Happens

Recurring incidents reveal systemic weaknesses. Engineers often address symptoms under pressure during active incidents. This provides immediate relief but leaves the underlying problem intact. Organizational dynamics contribute to this. Teams prioritize feature delivery over reliability work. Limited resources prevent deeper investigation or comprehensive remediation. High deployment frequency can also expose new failure vectors if testing is inadequate. Legacy systems frequently accrue technical debt. This debt manifests as hard-to-diagnose, interdependent failures. Inadequate monitoring capabilities hide emergent failure modes. Alerting may not trigger for partial or intermittent system degradation. A culture that penalizes failure instead of promoting learning also hinders effective root cause analysis. This leads to superficial fixes and incident recurrence.

Investigation Process

  1. Collect Incident Data. Gather all relevant incident tickets and post-mortems over a defined period.
  2. Identify Similarities. Group incidents sharing symptoms, affected services, or failure domains. Look beyond surface-level descriptions.
  3. Analyze Post-Mortems. Scrutinize the root causes identified. Note if a similar cause appears across different incidents. Evaluate the effectiveness of past remediations.
  4. Review Technical Changes. Correlate incident recurrences with recent deployments or infrastructure changes. Use a distributed system debugging workflow for complex interactions.
  5. Examine Monitoring and Alerting. Determine if current instrumentation detects the emerging failure. Assess its granularity and thresholds.
  6. Evaluate System Design. Identify architectural patterns consistently involved in failures. Look for single points of failure or cascading effects.
  7. Interview Involved Teams. Discuss operational pain points and known system limitations with engineers. Their practical knowledge is invaluable.
  8. Categorize Root Causes. Assign common categories such as race conditions, resource exhaustion, dependency failures, data corruption, misconfiguration, or deployment errors.
  9. Prioritize Remediation. Focus on patterns with high impact or frequent recurrence. Design solutions that address the systemic issue, not just the symptom.

Practical Example

A customer-facing API began experiencing intermittent 500 errors. Incident response typically involved restarting the API service. This resolved the issue for a few hours or days. Engineers initially attributed it to transient network issues. Over time, these incidents increased in frequency and duration. Reviewing incident logs revealed every outage coincided with high memory usage on a specific set of worker nodes. Initial post-mortems cited "resource contention." Deeper investigation found these nodes processed specific data transformation jobs. These jobs loaded large datasets into memory without proper garbage collection. The API service shared these worker nodes. The data jobs starved the API service of memory, causing unexpected process termination. The previous "fixes" only cleared memory temporarily. The actual root cause was an inefficient data processing job architecture. The API service failing was a symptom. The remediation involved isolating the data transformation jobs onto dedicated worker pools. This prevented memory contention with critical API services. Additionally, memory usage alerts were added for both job and API worker pools.

Preventing Recurrence

Preventing recurrence requires systemic changes. Implement a robust post-incident review process. This process must go beyond identifying symptoms. It must pinpoint deep architectural, process, or cultural root causes. Fund remediation efforts explicitly. Ring-fence capacity for reliability work. Prioritize these fixes alongside new features. Enhance monitoring and observability tools. Capture granular metrics and logs. Develop synthetic transactions to detect subtle degradations. Implement chaos engineering principles. Proactively test system resilience to known failure patterns. Automate deployment and rollback processes. Reduce human error during critical operational tasks. Formalize knowledge sharing among teams. Document failure modes and their resolutions centrally. Consider introducing queueing systems to decouple services and absorb spikes. This can prevent upstream failures from cascading.

What Teams Usually Do Instead

Teams often implement partial or localized fixes. They address the immediate symptom rather than the systemic problem. For example, increasing a timeout value instead of optimizing the slow query. They might restart services manually instead of investigating memory leaks. These actions relieve pressure temporarily. However, they leave the underlying fault intact. Often, incidents are blamed on single points of failure. The interdependent system behavior is ignored. Teams might also focus solely on post-mortems without a dedicated follow-up process. Action items from post-mortems are then deprioritized. They are often subsumed by new feature development. This creates an accumulation of technical debt. It also fosters a reactive, interrupt-driven operational model. Such a model reduces an engineering team's focus and productivity.

Key Takeaways

  • Address systemic root causes, not just symptoms.
  • Prioritize dedicated work for reliability improvements.
  • Improve monitoring to detect subtle failure patterns.
  • Formalize post-incident review and remediation processes.
  • Investigate architecture for inherent fragility and debt.

See also how we help teams build products and writing a post-incident review that helps.

Frequently Asked Questions

Why Do the Same Incidents Keep Recurring?

We usually find incomplete or localized fixes, missing monitoring for specific failure modes, architecture with inherent fragility, insufficient testing against known failures, and weak operational processes. Under pressure, engineers also address symptoms for immediate relief, which leaves the underlying problem intact.

How Do You Find Patterns Across Incidents?

We collect incident tickets and post-mortems over a defined period, group incidents that share symptoms, affected services or failure domains, and scrutinize the root causes recorded. We then correlate recurrences with deployments and infrastructure changes, and categorize causes such as race conditions, resource exhaustion and dependency failures.

What Did the Intermittent 500 Errors Example Reveal?

We saw an API restarted repeatedly with only temporary relief, until a review showed every outage coincided with high memory use on worker nodes shared with data transformation jobs. The real cause was the job architecture, so isolating those jobs onto dedicated worker pools and adding memory alerts fixed it.

How Do You Prevent Incidents From Recurring?

We run post-incident reviews that reach architectural, process or cultural causes, fund remediation explicitly, and ring-fence capacity for reliability work alongside features. We also improve monitoring and synthetic transactions, test resilience with chaos engineering, automate deployment and rollback, and document failure modes centrally.

What Do Teams Usually Do Instead?

We often see partial fixes such as raising a timeout instead of optimizing the slow query, manual restarts instead of investigating memory leaks, and post-mortems with no follow-up process. Action items then lose out to feature work, technical debt builds up, and the team stays in a reactive, interrupt-driven mode.

About the author

Better Software

Better Software Team

Product and engineering team

Better Software Team is the product and engineering team at Better Software. We build new software products and improve existing applications and systems, with deeper experience in healthcare, finance and energy.