Project health

Review project health, operation failures, and blocked storage use.

Check a project

curl "https://api.volcano.dev/projects/$PROJECT_ID/health" \
  -H "Authorization: Bearer $PLATFORM_TOKEN"

Request GET /projects?include=health to include the same status in project lists.

StatusMeaning
emptyNo functions, frontends, databases, storage, Volcano Auth users, or Sandbox resources are listed. A Sandbox template that is not being deleted, or a session that still holds capacity, counts, as long as the Sandbox API still lists it for the project.
healthyNo issues were reported by the available checks.
needs_attentionA failed or stalled operation needs review, or a frontend that serves needs a redeploy because edge recovery gave up. These records do not confirm an outage.
degradedA resource is only partly available, or is unavailable for an expected, temporary reason. See Degraded resources.
criticalUse is blocked, such as invocation of a failed function, connections to a failed database, a failed frontend with no deployment serving, or uploads above an enforced storage allowance.
unknownThe check cannot determine the status.

Frontends while a deployment builds

While a deployment builds, a frontend is provisioning, and the site keeps being served from the previous deployment. Health reports that deployment's state, not the build:

Before the deploymentWhile it builds
Serving normallyhealthy
Serving with incomplete edge synchronization (degraded)degraded, until a deployment completes or the build stalls
Nothing serving after a failed deploymentcritical (frontend_not_serving)
First deployment of a new frontendhealthy, because there is nothing to lose

A deployment that fails over a site that is still served does not change the status, because the status follows what serves the site: healthy when a healthy deployment still serves it, degraded when the serving deployment is degraded, and critical when nothing serves it. The failed attempt is only a deployment record.

A build that runs for 45 minutes or more is needs_attention (resource_provisioning_stalled), unless nothing is serving, which stays critical.

A frontend marked failed is critical (frontend_not_serving), whatever an earlier deployment's record says. A failed workflow leaves a frontend active while its site is live, so a failed frontend has no site up. Local mode marks a frontend failed when it abandons a deployment and does not restart its site until the next deployment.

While a deployment builds, a frontend serves a site only while it has a live edge URL and a deployed region. Volcano uses the same test to decide that a failed deployment, or a failed delete that rolled back, leaves a frontend active. A frontend without a live site is not serving, so it reads critical even when an older deployment's record is still active. A delete that has already torn the site down clears the URL, so a frontend whose cleanup failed and that is then redeployed is not read as serving a site that is gone.

Degraded resources

Two cases report degraded. In both, a resource is not in its normal state and Volcano is handling it.

  • A frontend whose edge synchronization did not complete (resource_degraded). The frontend keeps serving while Volcano retries edge recovery a limited number of times, and it stays degraded while an attempt is running. If those retries are spent, nothing retries it any more and it keeps serving until you redeploy it. It is then reported as needs_attention with frontend_edge_recovery_exhausted. The record of the exhausted retries is kept for 15 days, after which the frontend reads degraded again.
  • A database being restored (resource_restoring). The database does not accept connections until the restore finishes. It returns to active when the restore completes. If the restore cannot complete, the database becomes failed and the project is critical.

Review findings

The response includes checks and the highest-priority findings. Each finding contains a reason_code and the affected resource in scope.resource. Check data_status before treating a result as complete. A partial or stale result may be incomplete, so do not read healthy in it as a confirmation of current availability. observed_at identifies when the check ran. It is not when a failed operation happened, and a finding does not carry that time. The evidence.value of a lifecycle check is an identifier of its status (0 healthy, 1 degraded, 2 critical, 3 unknown, 4 needs attention) and not a severity order, so rank checks by status.

On a plan that stops at its allowance (HOBBY), the storage.capacity check judges the file storage of your whole account against the allowance, because the allowance is metered across every project you own. When the account has reached it, every project in it reports storage_usage_over_plan_limit, because uploads are refused from that point. On a plan that bills overage (SUPERAGENT), uploads are never refused, so the check compares only this project's bytes with the allowance and reports storage_usage_over_allowance or storage_usage_within_plan_limit for it alone. Its evidence describes only this project: value is the bytes this project stores and sample_count is its object count, so a project can report a small value while its account is over the allowance.

The status summarizes the findings and does not describe the whole project. A critical finding names the resource and the reason, for example function_invocation_blocked for calls to one function or storage_usage_over_plan_limit for uploads. It does not mean other parts of the project are unavailable.

{
  "project_id": "7f2b3c1e-0d4a-4c8e-9a51-2f6d8b0e1c34",
  "status": "needs_attention",
  "observed_at": "2026-10-13T13:30:00Z",
  "fresh_through": "2026-10-13T13:30:00Z",
  "data_status": "complete",
  "checks": [
    {
      "id": "lifecycle.project.7f2b3c1e-0d4a-4c8e-9a51-2f6d8b0e1c34",
      "category": "lifecycle",
      "status": "healthy",
      "reason_code": "resource_active",
      "scope": {
        "resource": {
          "type": "project",
          "id": "7f2b3c1e-0d4a-4c8e-9a51-2f6d8b0e1c34",
          "name": "my-app"
        }
      },
      "evidence": { "metric": "resource.lifecycle.status", "value": 0, "unit": "1", "sample_count": 1 }
    },
    {
      "id": "lifecycle.function.3b9e5d27-6c1a-4f08-8d2b-91a4c7e0f5a6",
      "category": "lifecycle",
      "status": "healthy",
      "reason_code": "resource_active",
      "scope": {
        "resource": {
          "type": "function",
          "id": "3b9e5d27-6c1a-4f08-8d2b-91a4c7e0f5a6",
          "name": "api",
          "kind": "standard"
        }
      },
      "evidence": { "metric": "resource.lifecycle.status", "value": 0, "unit": "1", "sample_count": 1 }
    },
    {
      "id": "workflow.status-refresh.function.3b9e5d27-6c1a-4f08-8d2b-91a4c7e0f5a6",
      "category": "lifecycle",
      "status": "needs_attention",
      "reason_code": "status_refresh_failed",
      "scope": {
        "resource": {
          "type": "function",
          "id": "3b9e5d27-6c1a-4f08-8d2b-91a4c7e0f5a6",
          "name": "api",
          "kind": "standard"
        }
      },
      "evidence": { "metric": "workflow.job.failure", "value": 1, "unit": "1", "sample_count": 1 }
    },
    {
      "id": "storage.capacity",
      "category": "storage",
      "status": "healthy",
      "reason_code": "storage_usage_within_plan_limit",
      "scope": {
        "resource": {
          "type": "project",
          "id": "7f2b3c1e-0d4a-4c8e-9a51-2f6d8b0e1c34",
          "name": "my-app"
        }
      },
      "evidence": { "metric": "storage.total_bytes", "value": 0, "unit": "By", "sample_count": 0 }
    }
  ],
  "findings": [
    {
      "id": "workflow.status-refresh.function.3b9e5d27-6c1a-4f08-8d2b-91a4c7e0f5a6",
      "category": "lifecycle",
      "status": "needs_attention",
      "reason_code": "status_refresh_failed",
      "scope": {
        "resource": {
          "type": "function",
          "id": "3b9e5d27-6c1a-4f08-8d2b-91a4c7e0f5a6",
          "name": "api",
          "kind": "standard"
        }
      },
      "evidence": { "metric": "workflow.job.failure", "value": 1, "unit": "1", "sample_count": 1 }
    }
  ]
}

checks lists every check, including the healthy ones. findings lists up to five of the critical, degraded, and needs_attention checks, most severe first. A resource being deleted is healthy with resource_deleting, because the removal was requested. If the deletion fails, the resource becomes failed and is classified like any failed resource, and its failed cleanup task is needs_attention. A check with status unknown appears in checks but not in findings. If the plan cannot be looked up, the storage.capacity check reports unknown with plan_unavailable and data_status is partial. That check does not change the project status, which comes from the remaining checks. On a plan that stops at its allowance, the check also reports unknown with storage_unavailable when your account's total storage cannot be read.

An empty project can retain a failed project record or an unfinished cleanup task. Its label remains empty; its findings still identify operations that need review. empty describes what the project contains and does not mean there is nothing to review, so show the findings beside it. A failed project record alone does not identify which operation failed.

How long a finding lasts

A finding describes an unresolved operation or state, and it ends when the evidence does:

  • A failed status refresh counts only while its workflow is the resource's current one. A newer deployment ends it.
  • A failed cleanup task stays until the cleanup succeeds. A successful cleanup removes the record.
  • Edge recovery that gave up stays until the next deployment. The record of it is kept for 15 days, after which the frontend reads degraded again.
  • A provisioning function or database is a finding only when it has no start time or has run for 45 minutes or more. A frontend reads by the deployment it is served from instead (see above).

Health describes recorded lifecycle and storage state. It is not a live availability probe. A failed deployment does not establish whether the published version is available. A function whose current state is failed is critical because Volcano refuses invocation in that state; its finding uses function_invocation_blocked. A failed workflow alone remains needs_attention. Use deployment history to inspect its result. A failed cleanup task can require review even after the resource is no longer listed.

On this page