# BYOC Pinning

[Namespace pinning](/docs/pinning) reserves dedicated query nodes for a
namespace, so it stays warm on local SSD and gets predictable throughput and
latency. On a BYOC cluster, the pinned nodes run in your own cloud account.

Your BYOC kit lists the node types you can pin to. When you pin a namespace, you
choose one, and each of its replicas gets a dedicated node of that type. Nodes
are created when you pin and removed after you unpin, so you only pay for them
while the namespace is pinned.

### Enable pinning

#### GCP

Add the node types to the `turbopuffer.tfvars` of your BYOC kit. For each one,
list the SKUs it can run on and the vCPU, memory, and local SSD of one node.
Names are lowercase letters, digits, `-` or `.`.

```hcl
query_pinning_node_types = {
  "medium" = {
    # GCP uses whichever of these has capacity
    skus       = ["c4a-highmem-32-lssd", "c4-highmem-32-lssd"]
    cpu        = 32
    memory_gib = 248
    disk_gib   = 1875
  }
  "large" = {
    skus       = ["c4a-highmem-72-lssd"]
    cpu        = 72
    memory_gib = 576
    disk_gib   = 6000
  }
}
```

Listing more than one SKU lets a node type run on any of them, so pinning still
works when one is out of capacity. Set `cpu`, `memory_gib`, and `disk_gib` from
the smallest SKU listed.
#### AWS

In your BYOC kit's `turbopuffer.tfvars`, define the node types you want to run.
For each node type, give its instance type and the vCPU, memory, and local NVMe
capacity of a single node. The instance type must have local NVMe storage, such
as the `i8g` or `i7i` families. Node type names may contain only lowercase
letters, digits, `-`, and `.`.

```hcl
query_pinning_node_types = {
  "medium" = {
    instance_type = "i8g.8xlarge"
    cpu           = 32
    memory_gib    = 256
    disk_gb       = 7500
  }
  "large" = {
    instance_type = "i8g.16xlarge"
    cpu           = 64
    memory_gib    = 512
    disk_gb       = 15000
  }
}
```
#### Azure

In your BYOC kit's `turbopuffer.tfvars`, define the node types you want to run.
For each node type, give its VM size and the vCPU, memory, and local NVMe
capacity of a single node. The VM size must have local NVMe storage, such as
the `Lsv3` or `Lasv3` series. Node type names may contain only lowercase
letters, digits, `-`, and `.`.

```hcl
query_pinning_node_types = {
  "medium" = {
    sku        = "Standard_L32s_v3"
    cpu        = 32
    memory_gib = 256
    disk_gib   = 7152
  }
  "large" = {
    sku        = "Standard_L64s_v3"
    cpu        = 64
    memory_gib = 512
    disk_gib   = 14305
  }
}
```

Check that the region has enough vCPU quota for pinned nodes on top of your
regular query and index nodes. Each replica gets its own node, and a sharded
namespace pins every shard separately, so a namespace with 4 shards and 2
replicas uses 8 nodes.

Apply the change:

```bash
terraform apply -var-file=turbopuffer.tfvars
```

#### GCP

This regenerates `values.yaml` and `compute_classes.yaml`. Apply the compute
classes, then roll out `values.yaml` with `helm upgrade` as described in
[Configuration](/docs/byoc/configuration).

```bash
kubectl apply -f compute_classes.yaml
```
#### AWS

This regenerates `values.yaml`. Roll it out with `helm upgrade` as described in
[Configuration](/docs/byoc/configuration).
#### Azure

This regenerates `values.yaml`. Roll it out with `helm upgrade` as described in
[Configuration](/docs/byoc/configuration).

### Pin a namespace

Pin with the [metadata API](/docs/metadata#change-metadata).

```bash
curl -X PATCH "https://<cluster_endpoint>/v1/namespaces/<namespace>/metadata" \
  -H "Authorization: Bearer <api_key>" \
  -H "Content-Type: application/json" \
  -d '{"pinning": {"node_type": "large", "replicas": 2}}'
```

Always set `node_type` to one of the node types you defined. turbopuffer does
not choose or change it for you. Once pinned, watch `pinning.status.utilization`
in the namespace metadata. It is the highest of `utilization_cpu`,
`utilization_disk`, and `utilization_disk_io`, which are also reported. High
utilization values mean the namespace may need more replicas or a larger node
type. To resize, send the same `PATCH` with a new `node_type`.

If your cloud provider has no capacity for the node type, the pin waits until a
node can be created. Queries keep working on the regular query nodes in the
meantime. Check progress with `GET /v1/namespaces/:namespace/metadata`.

To see the pinned pods and the nodes they run on:

```bash
kubectl get pods -n turbopuffer -o wide \
  -l turbopuffer-query-pinning-target-node-type=large
```

See [Pinning](/docs/pinning) for replicas and monitoring.


---

This page: [/docs/byoc/pinning.md](https://turbopuffer.com/docs/byoc/pinning.md)

All documentation pages: [/llms.txt](https://turbopuffer.com/llms.txt)

All documentation in one file: [/llms-full.txt](https://turbopuffer.com/llms-full.txt)
