---
title: "Channel Health"
method: GET
path: "/me/apps/{app_id}/channels/{channel_id}/health"
---

# Channel Health

`GET /me/apps/{app_id}/channels/{channel_id}/health`

## Request

- Base URL: `https://api.xhostd.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.xhostd.com/me/apps/{app_id}/channels/{channel_id}/health`
- Auth: none declared

Report why one channel is slow or unhealthy, plus what to do.

The reply carries five blocks and a findings list. The resource
block covers the OWNER's whole account, so a member reads it as not
available. The runtime block reads the container status facts off
the host. The build block counts the recent builds the kernel
stopped. The database block reads the channel's own cell Postgres.
The latency block reads the request-duration histogram of the
channel over the last day, and it covers the server-side span
alone.

A source the route cannot read reports ``available=false`` with a
reason, and the route still answers 200. The findings list is never
empty: a channel with no fault carries the ``healthy`` finding.

The control-DB read only reads, so it runs on
``run_read_in_thread``. The host read and the database read follow
it and each degrade on their own.

## Path parameters

- `app_id` string, uuid, required
- `channel_id` string, uuid, required

## Headers

- `authorization` string, nullable

## Response `200`

Successful Response

- ChannelHealth: The whole diagnosis of one channel.
  - `app_id` string, uuid, required
  - `channel_id` string, uuid, required
  - `resource` ResourceHealth, required: Recent CPU, memory, pressure and disk figures of the account.
    - `available` boolean, required
    - `reason` string, nullable, required
    - `cpu_pct_of_limit` number, nullable, required
    - `cpu_soft_cores` number, nullable, required
    - `mem_peak_bytes` integer, nullable, required
    - `mem_limit_bytes` integer, nullable, required
    - `psi_full_avg60_peak` number, nullable, required
    - `io_psi_some_avg60_peak` number, nullable, required
    - `oom_kills` integer, nullable, required
  - `runtime` RuntimeHealth, required: Restart and exit facts of the channel's app container. The block describes the running container when one exists, else the newest container of the channel, live or archived. ``container_index``, ``container_id``, and ``source`` name that container. ``started_at`` is docker's last start of it, which a restart-policy restart moves forward; ``restart_count`` counts those restarts.
    - `available` boolean, required
    - `reason` string, nullable, required
    - `container_index` integer, nullable, required
    - `container_id` string, nullable, required
    - `source` 'live' | 'archive', nullable, required
    - `running` boolean, nullable, required
    - `status` string, nullable, required
    - `exit_code` integer, nullable, required
    - `oom_killed` boolean, nullable, required
    - `restart_count` integer, nullable, required
    - `started_at` string, nullable, required
    - `finished_at` string, nullable, required
  - `build` BuildHealth, required: Recent builds of this channel that the kernel stopped.
    - `available` boolean, required
    - `reason` string, nullable, required
    - `oom_kill_count` integer, nullable, required
    - `last_oom_kill_at` string, nullable, required
  - `database` DatabaseHealth, required: Size, cache-hit percent and top statements of the channel DB.
    - `available` boolean, required
    - `reason` string, nullable, required
    - `size_bytes` integer, nullable, required
    - `cache_hit_pct` number, nullable, required
    - `top_statements` StatementsHealth, required: The slowest statements of the channel database.
      - `available` boolean, required
      - `reason` string, nullable, required
      - `statements` TopStatement[], required
        - `query` string, required
        - `truncated` boolean, required
        - `calls` integer, required
        - `total_exec_ms` number, required
        - `mean_exec_ms` number, required
        - `rows` integer, required
  - `latency` LatencyHealth, required: How long this channel took to answer its recent requests. Every figure covers the SERVER-SIDE span alone: the edge starts the clock when it reads the request, and stops it when it writes the last byte of the reply. The TCP handshake, the accept queue and the TLS handshake all end before that clock starts, so a stall while the visitor connects is invisible here. The transfer of the reply is inside the span, so a slow visitor link raises the figure. A high figure alone does not prove that the app is slow, and no figure states an end-to-end time. ``p50_ms``, ``p95_ms`` and ``p99_ms`` are upper bounds off the histogram edges, not measured durations: 95 of every 100 requests finished under ``p95_ms``. ``max_ms`` is the one measured figure among them, and it is the worst request of the window. ``window_hours`` names the scope of the read, so it stays present when the block is not available. It states what the route looked at, and it measures nothing about the channel. ``slow_request_threshold_ms`` follows that same rule: it states the reader's cut and measures nothing, so it also stays present in both states. The cut is STRICTLY ABOVE the figure. The console cannot import ``SLOW_REQUEST_MS``, so the payload carries it and the page states one number with the route.
    - `available` boolean, required
    - `reason` string, nullable, required
    - `window_hours` integer, required
    - `slow_request_threshold_ms` integer, required
    - `requests` integer, nullable, required
    - `p50_ms` integer, nullable, required
    - `p95_ms` integer, nullable, required
    - `p99_ms` integer, nullable, required
    - `max_ms` integer, nullable, required
    - `slow_requests` integer, nullable, required
    - `slow_request_pct` number, nullable, required
    - `by_proto` LatencyProto[], required
      - `proto` string, required
      - `requests` integer, required
      - `p95_ms` integer, required
  - `findings` Finding[], required
    - `code` string, required
    - `severity` 'info' | 'warning' | 'critical', required
    - `what` string, required
    - `why` string, required
    - `action` FindingAction, required: What to do about one finding, and who does it. ``do`` is a closed set, so a reader never parses prose to learn whether a machine may try again. ``retry_after_seconds`` is necessary for ``retry`` and for ``wait``, and forbidden for every other verb.
      - `do` 'wait' | 'retry' | 'change_code' | 'upgrade_plan' | 'contact_support' | 'none', required
      - `actor` 'agent' | 'user', required
      - `retry_after_seconds` integer, nullable, required

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/xhostd/apis/xhostd-public.md) · [All operations](https://skmtc.dev/xhostd/apis/xhostd-public/llms.txt) · [OpenAPI document](https://skmtc.dev/xhostd/apis/xhostd-public/revisions/bf439c4d1789?raw)
