---
title: Health Status
description: How Mergify decides whether a test is healthy, flaky, or broken, and what moves it from one state to another.
---

Every test is in one of three states: **healthy**, **flaky**, or **broken**.
Mergify tracks a test per repository, branch, pipeline, job, and test name, so
the same test can be healthy on one branch and flaky on another.

Mergify reads a test's runs one at a time, in the order they finished, and
ignores skipped runs. Each run can move the test at most one step, and a run
that matches none of the arrows below leaves the test where it is. Only
runs move a test: a test that stops running keeps its state, and time alone
never makes it healthy.

```dot class="flow" title="Test health states: a failure makes a test unhealthy, a streak of clean passes brings it back"
digraph {
  splines="ortho";
  nodesep=0.5;
  ranksep=0.4;

  // Each edge label is a node of its own: orthogonal routing cannot place
  // edge labels, so the label sits on the edge it names.
  node [shape=plaintext, fontsize=11, margin="0.12,0.04", width=0, height=0, class="chrome"];
  failure [label="failure"];
  few_clean [label="a few\nclean passes"];
  evidence_from_healthy [label="flaky evidence"];
  long_clean [label="a longer streak of\nclean passes over\nseveral days"];
  evidence_from_broken [label="flaky evidence"];
  fail_streak [label="fails on several\ncommits in a row"];

  node [shape=box, fontsize=14, margin="0.24,0.15", height=0.42];
  healthy [label="Healthy", shape=oval, class="merged"];
  broken [label="Broken", class="failed"];
  flaky [label="Flaky", class="flagged"];

  // Invisible edges keep the labels in the same order as the states they join.
  { rank=same; failure -> few_clean -> evidence_from_healthy -> long_clean [style=invis]; }
  { rank=same; broken -> evidence_from_broken -> flaky [style=invis]; }

  // Edges leading up are written top-down with dir=back, so they do not
  // pull the healthy state below the others.
  healthy -> failure [arrowhead=none];
  failure -> broken;
  healthy -> few_clean [dir=back];
  few_clean -> broken [arrowhead=none];
  healthy -> evidence_from_healthy [arrowhead=none];
  evidence_from_healthy -> flaky;
  healthy -> long_clean [dir=back];
  long_clean -> flaky [arrowhead=none];
  broken -> evidence_from_broken [arrowhead=none, constraint=false];
  evidence_from_broken -> flaky [constraint=false];
  broken -> fail_streak [dir=back];
  flaky -> fail_streak [arrowhead=none];
}
```

## Flaky evidence

A failure alone does not make a test flaky. Mergify needs evidence that the
outcome does not follow from the code, and any of these counts:

- **Same commit, different result**: the test both passed and failed on the
  same commit.

- **Marked flaky**: your test framework reported the run as flaky, even if it
  passed.

- **Intermittent failure**: the test fails on a new commit after passing since
  its last failure, and that last failure is recent. This holds even if the
  test recovered in between, so a test that keeps failing now and then ends up
  flaky, not broken.

A **clean pass** is a passing run with no flaky evidence. Any failure, or any
run with flaky evidence, restarts the streak of clean passes.

A flaky test takes longer to recover than a broken one. A broken test that
starts passing has most likely been fixed, while a flaky test can pass for a
while before failing again, so Mergify waits for a longer streak spread over
time before calling it healthy.

## Example

Here is one test, run by run:

1. It fails on commit `a1`. Nothing points to flakiness, so it is **broken**.

2. It passes cleanly on the next few commits and goes back to **healthy**.

3. Two days later, it fails on commit `e5`. It passed since its recent failure
   on `a1`, so this failure is intermittent: the test is now **flaky**.

4. A rerun of `e5` fails again. Reruns of the same commit count once toward
   the failing streak that would make it broken, so the test stays flaky.

5. Another rerun of `e5` passes. Same commit, different result: still flaky,
   and the clean streak has not started.

6. It then passes cleanly on new commits, many times over several days, and
   goes back to **healthy**.

## Related pages

- [Detection](/test-engine/detection) lists your tests by state and helps you
  decide which ones to fix first.

- [Quarantine](/test-engine/quarantine#when-mergify-quarantines-a-test-itself) explains when
  Mergify quarantines a test based on its state.
