---
title: "List serving deployments (platform admin)"
method: GET
path: "/v1/admin/inference/deployments"
tags: ["Internal"]
---

# List serving deployments (platform admin)

`GET /v1/admin/inference/deployments`

Cursor-paginated. Filterable by status and by publicModelId; with no filter every status partition is walked in declared order behind one opaque cursor.

## Query parameters

- `limit` integer
- `cursor` string
- `status` string
- `publicModelId` string

## Response `200`

Page of deployments

- ServingDeploymentPage
  - `items` ServingDeployment[], required
    - `backendCatalogWeight` integer — Live catalog routing weight of this deployment's backend. Only present when backendRegistered is true. May differ from backendWeight (the row mirror) while a rollout ramp is in flight.
    - `backendHealthy` boolean — Live catalog health of this deployment's backend (the kill switch). Only present when backendRegistered is true.
    - `backendRegistered` boolean — Whether this deployment's pool:// backend is currently present on the catalog model row. Absent when the live catalog state could not be read; false until the first replica passes readiness.
    - `backendVersion` string — The rollout tag this deployment's backend reports to the gateway as the `version` metric label on ig_model_requests_total and ig_stream_ttft_seconds. Use it to separate the two sides of a rollout in a dashboard query. Only present when backendRegistered is true.
    - `backendWeight` integer, required — Routing weight of the catalog backend. 0 = standby (blue/green starts here)
    - `changeCause` string — Operator-supplied reason for the revision that created this deployment
    - `createdAt` string, required
    - `dtype` string
    - `engine` string, required — Inference engine, e.g. vllm or sglang
    - `engineImage` string — Engine container image override; absent = the engine's default
    - `env` object
    - `extraArgs` string[]
    - `generation` integer — 1 for a hand-created deployment, parent+1 for each revision. History ordering only: the controller never reads it, because rollout adoption is the explicit rolloutRole opt-in and nothing else.
    - `gpuCountPerReplica` integer, required
    - `gpuModelId` string, required
    - `id` string, required
    - `isolated` boolean, required — True when replicas and their private endpoint pool are for direct operator testing only. Isolated deployments never register a catalog backend, never participate in blue/green rollout, and cannot receive gateway traffic.
    - `maxConcurrencyPerReplica` integer
    - `maxModelLen` integer
    - `maxPromptBytes` integer — Exclusive text-request byte ceiling for routing eligibility; 0 or absent = unbounded. Routing hint only, not a context limit.
    - `minPromptBytes` integer — Inclusive text-request byte floor for routing eligibility; 0 or absent = unbounded. Routing hint only, not a context limit.
    - `nativeFamilies` string[]
    - `nodePool` string — Stable logical capacity lane within the public model. Blue/green only replaces versions in the same node pool; empty preserves legacy model-wide grouping.
    - `organizationId` string, required — Org that owns the managed replicas (and their metering)
    - `parentDeploymentId` string — The deployment this one was revised from. Set only by /revise, so an absent value means this deployment was created by hand.
    - `poolId` string — Endpoint pool the deployment's replicas register in
    - `publicModelId` string, required — Catalog model this deployment serves capacity for
    - `quantization` string
    - `readyReplicas` integer, required
    - `replicaRuntime` '' | 'vm' | 'pod' — How each replica is placed. Absent or "" or "vm" = a QEMU/VFIO VM on the baremetal fleet (the legacy shape; every pre-existing deployment reads as this). "pod" = a hardened GPU pod on a provider-onboarded runc node. One deployment is one runtime; a public model mixes runtimes through lanes.
    - `replicaVmIds` string[]
    - `replicasDesired` integer, required
    - `replicasMax` integer, required
    - `replicasMin` integer, required
    - `rollout` ServingRolloutState — DERIVED rollout state for this deployment's lane (public model + node pool). Computed by the same code that drives the rollout, so an operator surface can never narrate a different story than the controller will execute. Absent when the deployment is isolated, terminal, or the live catalog could not be read. forced / forceExpired / forcedBy / forcedReason are the ONLY read of a force-cutover: the arm expires, so the raw stamp on the row answers "is a force in effect" wrong roughly as often as it answers it right, and it is deliberately not on the wire.
      - `bluePoolPolicy` string — Member-selection policy on the blue side's endpoint pool. Absent when the lane has no blue with a pool.
      - `blueSlots` integer — The blues' combined ready serving capacity, same unit
      - `cutoverReady` boolean — Whether green has the capacity parity cutover requires (>=95% of blue's slots)
      - `forceExpired` boolean — Force-cutover was armed but its window has elapsed, so it is inert. Set instead of forced, so a stale arm reads as expired rather than as an override nobody notices is still in effect.
      - `forced` boolean — Force-cutover is armed AND still inside its window, so the slot-derived gates (the weight ceiling and the parity bar) are being overridden this pass. Readiness, the step limit, and the two-pass separation are never overridden.
      - `forcedBy` string — Actor who armed force-cutover
      - `forcedReason` string — Why force-cutover was armed
      - `greenPoolPolicy` string — Member-selection policy on the green's endpoint pool
      - `greenSlots` integer — Green's ready serving capacity: readyReplicas x maxConcurrencyPerReplica
      - `lane` string, required — The lane's label, publicModelId/nodePool
      - `laneMemberIds` string[] — Every live deployment in this lane, oldest first
      - `laneWeight` integer — The lane's full weight: the largest weight any blue carries
      - `nextAction` string — One sentence naming what the controller will do next and why, written by the deciding code itself.
      - `paused` boolean — The green row carries an operator pause. The ramp is frozen at its current share; traffic is untouched.
      - `peerId` string — The other side of the roll: for a green, the newest blue it replaces; for a blue, the green replacing it. Absent when the lane is not rolling.
      - `phase` 'none' | 'waiting_for_replicas' | 'ramping' | 'capacity_hold' | 'at_full_weight' | 'cut_over' | 'rolled_back' | 'paused', required — Where a roll is. capacity_hold is the state the capacity guard produces: green is ramped as far as its serving capacity justifies and will not advance until it is scaled up. paused is an operator hold: the ramp is frozen at its current share and traffic is untouched, which is categorically weaker than rolled_back.
      - `policyMismatch` boolean — The two sides run different member-selection policies, so the rollout is not a controlled comparison: whatever the new version measures includes the balancing change.
      - `role` 'independent' | 'blue' | 'green', required — A deployment's part in its lane RIGHT NOW. independent = carries its own weight and is not in a rollout (also what every lane member is when no green exists). blue = an older member a green is ramping against. green = the opted-in successor.
      - `weightCeiling` integer — The highest weight green may carry right now under the capacity guard (its share of the lane's ready serving slots, scaled onto laneWeight).
    - `rolloutPaused` boolean — True while an operator has paused the ramp. Traffic is untouched: the deployment keeps the weight it holds and keeps serving, and the controller takes no rollout action until resume. The pause is also on rollout.paused; this raw column is what a surface falls back to when the lane could not be read at all.
    - `rolloutRole` '' | 'green' — Opt-in blue/green role. Empty (default) = an INDEPENDENT weighted capacity member of its lane, never blue or green. "green" = the lane's successor generation: the controller ramps it against the older members under a capacity guard and cuts them over once it reaches capacity parity. Rollouts are never implicit.
    - `servedModelId` string, required — Model id the engine serves; must equal the catalog backend ref
    - `status` 'pending' | 'deploying' | 'ready' | 'degraded' | 'scaling' | 'draining' | 'stopped' | 'failed', required
    - `statusReason` string — Human-readable cause for degraded/failed states
    - `updatedAt` string, required
    - `version` string — Generation marker for blue/green within one public model and node pool
    - `weightsRef` string — Staged-checkpoint reference; absent = the engine loads from its own source
  - `nextCursor` string — Opaque; pass back to continue. Absent/empty = no more pages

## Other responses

- `400` — The request is invalid
- `401` — Missing or invalid API key
- `403` — API key lacks the required scope
- `503` — A required integration (e.g. payments) is not configured

---

[API](https://skmtc.net/openrelay/apis/openrelay-api.md) · [All operations](https://skmtc.net/openrelay/apis/openrelay-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/openrelay/openrelay-api/revisions/7e2fe85577f4/schema)
