---
title: "Scale a node pool"
method: POST
path: "/v1/kubernetes/clusters/{id}/node-pools/{poolId}/scale"
tags: ["Kubernetes"]
---

# Scale a node pool

`POST /v1/kubernetes/clusters/{id}/node-pools/{poolId}/scale`

Sets the pool's node count. Scaling down drains the nodes it removes first. A cluster that is creating, deleting or failed answers 409 INVALID_CLUSTER_STATE; a failed cluster has no control plane to join. Needs clusters:write on an API key, or the owner, admin or member role on a session.

## Path parameters

- `id` string, required
- `poolId` string, required

## Request body

- ScaleKubernetesNodePoolRequest
  - `count` integer, required — The pool's new node count. Delete the pool to remove every node.
  - `expectedCount` integer — Optional count the caller reviewed. If the current count differs, answers 409 CONCURRENT_UPDATE without scaling. The comparison and write are atomic.

## Response `202`

Scaling started

- KubernetesNodePool — A set of identical whole-host nodes in one cluster.
  - `clusterId` string, required
  - `count` integer, required — Nodes the pool holds once it converges.
  - `createdAt` string, required
  - `id` string, required
  - `name` string, required
  - `readyCount` integer, required — Nodes that joined the cluster and are Ready.
  - `sku` KubernetesNodePoolSku, required — What every node in a pool is: exactly one of gpuModelId or cpuSku. Nodes are whole hosts, so a GPU node is a host of that model with every GPU passed through to it, and a CPU node is a whole CPU host. A cluster mixes SKUs through several pools.
    - `cpuSku` string — Whole-host CPU SKU.
    - `gpuModelId` string — GPU model, one of listGpuModels.
  - `status` 'creating' | 'ready' | 'scaling' | 'deleting' | 'failed', required

## Other responses

- `400` — The request is invalid
- `401` — Missing or invalid API key
- `403` — The caller is authenticated but may not do this. As on every operation, the caller's role or the API key's scope does not allow it, or the request targets another organization (FORBIDDEN, or NOT_A_MEMBER for a session), or the organization is suspended pending review (ORG_SUSPENDED) or has been deleted (ORG_DISABLED). This operation can also be refused because of the account. A new workload (a VM or pod create, a VM fork, a Kubernetes cluster or node pool create, a node pool scaled up) answers INSUFFICIENT_BALANCE, ACCOUNT_RESTRICTED or ACCOUNT_PENDING_VERIFICATION; a restart or reboot answers INSUFFICIENT_BALANCE; an API key create answers ACCOUNT_RESTRICTED or ACCOUNT_PENDING_VERIFICATION; a deposit or card save answers ACCOUNT_PENDING_VERIFICATION, VERIFICATION_UNAVAILABLE or FUNDING_UNDER_REVIEW; and a runner pool create answers ACCOUNT_PENDING_VERIFICATION. Every gate also answers ACCOUNT_SUSPENDED for a suspended organization, but only platform admins and internal callers reach it: a customer's request for a suspended organization is refused at authentication with ORG_SUSPENDED before it gets to a gate. A new API key or a wider scope clears none of these; see [Account and balance refusals](https://docs.openrelay.inc/docs/errors#account-and-balance-refusals) for what each one means and what to do.
- `404` — Resource not found
- `409` — The request conflicts with existing state

## Changes

- **2026-10-03** `bcf63adad2c3` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/openrelay/apis/openrelay-api/changes/v1/kubernetes/clusters/:id/node-pools/:poolId/scale/post.md)

---

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