---
title: "List a serving deployment's generation chain (platform admin)"
method: GET
path: "/v1/admin/inference/deployments/{id}/revisions"
tags: ["Internal"]
---

# List a serving deployment's generation chain (platform admin)

`GET /v1/admin/inference/deployments/{id}/revisions`

The revision history: this deployment's ancestry and its descendants in the same lane, each with the field diff against its parent, class labeled. Terminal generations are included, because they ARE the history: "what changed between the generation that worked and this one" is the question the chain exists to answer. env diffs report key names only. Returns the whole chain in one response: the walk is bounded at 50 generations, so there is nothing to page through.

## Path parameters

- `id` string, required

## Response `200`

The generation chain

- ServingRevisionPage — One deployment's whole generation chain. Not paged: the chain is bounded by the walk itself (50 generations), and a history an operator cannot see whole is not a history.
  - `items` ServingRevision[], required
    - `deployment` ServingDeployment, required — A self-hosted serving deployment: the durable intent to run N replicas of an inference engine for one public catalog model, plus the runtime state the reconcile loop maintains while converging on it.
      - `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
    - `diffFromParent` ServingSpecDiffEntry[] — What this generation changed against its parent. Absent for the root generation, and for a generation whose parent row no longer exists.
      - `class` 'structural' | 'routing' | 'sizing' | 'replica', required — How a spec field may be changed. structural makes a different lane or tenant and is rejected everywhere. routing is safe to mutate under a running replica (PATCH). sizing is mutable by adding or removing replicas (/scale). replica requires new processes on new hardware, which is the blue/green trigger, and is the default for any field not listed.
      - `field` string, required
      - `from` string — The source generation's value, stringified; absent when unset
      - `to` string — The new generation's value, stringified; absent when unset

## Other responses

- `400` — The request is invalid
- `401` — Missing or invalid API key
- `403` — API key lacks the required scope
- `404` — Resource not found
- `409` — The request conflicts with existing state
- `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/ed76b41e8006/schema)
