Argo CD Health Status Explained: Aggregation Logic and Custom Checks

Argo CD health status aggregates individual Kubernetes resource health using a priority-based ranking system (Healthy → Suspended → Progressing → Missing → Degraded → Unknown) and supports extensible Lua scripts for custom resource definitions.

Argo CD continuously monitors the health of deployed applications by evaluating every managed resource in the cluster. According to the argoproj/argo-cd source code, the controller’s health determination logic combines built-in Go implementations for standard resources with configurable Lua overrides for custom CRDs, providing real-time visibility through both the web UI and CLI.

How Argo CD Aggregates Application Health Status

The core health aggregation logic resides in the controller’s setApplicationHealth function, located in controller/health.go. This function evaluates each resource managed by an application and determines the overall health using a five-step process:

  1. Filters ignored resources – Resources annotated with argocd.argoproj.io/ignore-healthcheck: "true" are skipped (lines 46‑49).

  2. Skips self-referential applications – An application that manages itself does not affect its own health status (line 58).

  3. Retrieves individual health – For existing resources, the controller invokes health.GetResourceHealth from gitops-engine/pkg/health/health.go, applying any Lua overrides.

  4. Applies priority-based aggregation – The application inherits the most severe status from its constituent resources, following the priority order: Healthy → Suspended → Progressing → Missing → Degraded → Unknown.

  5. Records degradation causes – When health is degraded, the controller tracks up to three responsible resources using the maxHealthCausesShown constant and formats them via the formatHealthCauses function.

Built-In Health Checks for Standard Kubernetes Resources

Argo CD ships with Go-based health implementations for common Kubernetes resource types located under gitops-engine/pkg/health/. These built-in checks evaluate specific conditions without requiring custom configuration:

  • Deployment (health_deployment.go): Verifies that observedGeneration matches the desired generation and that replica counts are up-to-date.

  • Service (health_service.go): For LoadBalancer types, checks for the presence of an external IP or hostname.

  • Ingress (health_ingress.go): Validates that a load-balancer ingress entry exists.

  • CronJob (health_cronjob.go): Evaluates the last schedule status to determine if the resource is Progressing or Degraded.

These implementations return a HealthStatus struct that the controller aggregates according to the priority rules defined in controller/health.go.

Custom Health Checks with Lua Scripts

When managing custom resource definitions (CRDs) that lack built-in checks, Argo CD allows operators to define health logic using Lua scripts. The Lua engine implementation in util/lua/lua.go loads and executes these scripts at runtime, producing a HealthStatus struct with status and optional message fields.

Defining Custom Health Scripts

Place Lua scripts in the resource_customizations/<group>/<kind>/health.lua path, or register them via the argocd-cm ConfigMap using the key resource.customizations.health.<group>_<kind>. For example, to enable standard Lua libraries for a specific check, use the resource.customizations.useOpenLibs.<group>_<kind> key.

The following example configures a custom health check for cert-manager.io/Certificate resources:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  resource.customizations.useOpenLibs.cert-manager.io_Certificate: "true"
  resource.customizations.health.cert-manager.io_Certificate: |
    hs = {}
    if obj.status ~= nil then
      if obj.status.conditions ~= nil then
        for _, condition in ipairs(obj.status.conditions) do
          if condition.type == "Ready" and condition.status == "False" then
            hs.status = "Degraded"
            hs.message = condition.message
            return hs
          end
          if condition.type == "Ready" and condition.status == "True" then
            hs.status = "Healthy"
            hs.message = condition.message
            return hs
          end
        end
      end
    end
    hs.status = "Progressing"
    hs.message = "Waiting for certificate"
    return hs

Wildcard Support for Resource Groups

You can apply health checks to entire API groups or kinds using wildcards (*). The implementation uses the doublestar glob library to match patterns such as *.aws.crossplane.io/*:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  resource.customizations: |
    "*.aws.crossplane.io/*":
      health.lua: |
        hs = {}
        if obj.status ~= nil and obj.status.state == "available" then
          hs.status = "Healthy"
        else
          hs.status = "Degraded"
          hs.message = obj.status.state or "unknown"
        end
        return hs

Monitoring Health Status in the Argo CD UI and CLI

Once calculated, health status surfaces in both the web interface and command-line tools, reflecting the aggregation logic from controller/health.go.

Web UI: The Applications view displays an aggregated health badge. Selecting a specific resource reveals its individual health status and a "Caused by …" summary generated by the formatHealthCauses function.

CLI: The argocd app get command (implemented in cmd/argocd/commands/app.go) retrieves and displays the current health status along with problematic resources:

argocd app get my-app --refresh

Example output includes:


Health: Degraded
Caused by apps/Deployment:default/nginx-deployment

Summary

  • Argo CD determines application health status by aggregating individual resource health using the priority order: Healthy → Suspended → Progressing → Missing → Degraded → Unknown.
  • The aggregation logic lives in controller/health.go, specifically the setApplicationHealth function, which respects ignore annotations and skips self-referential applications.
  • Built-in checks for standard resources (Deployments, Services, Ingresses) reside in gitops-engine/pkg/health/ and evaluate resource-specific conditions.
  • Custom Lua scripts extend health checking to CRDs via argocd-cm ConfigMap entries or resource_customizations/ paths, with wildcard support using the doublestar library.
  • Degradation causes are tracked (up to three resources via maxHealthCausesShown) and displayed in both the UI and CLI.

Frequently Asked Questions

How does Argo CD determine the overall health of an application?

Argo CD evaluates every managed resource through the setApplicationHealth function in controller/health.go. It polls each resource's health status—using built-in Go logic or custom Lua scripts—and assigns the application the most severe status found, following the priority chain from Healthy (best) to Unknown (worst).

Can I disable health checks for specific resources?

Yes. Add the annotation argocd.argoproj.io/ignore-healthcheck: "true" to any resource manifest. The controller will skip health evaluation for that resource during aggregation, as implemented in lines 46‑49 of controller/health.go.

Where are custom Lua health scripts stored in the Argo CD configuration?

Custom scripts can be placed in the resource_customizations/<group>/<kind>/health.lua file path within your Argo CD configuration, or defined inline in the argocd-cm ConfigMap using keys like resource.customizations.health.<group>_<kind>. The Lua engine in util/lua/lua.go executes these scripts at runtime.

What is the priority order for Argo CD health statuses?

Argo CD uses the following priority order when aggregating health status, from least severe to most severe: Healthy, Suspended, Progressing, Missing, Degraded, Unknown. The application status reflects the worst condition present among its managed resources.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →