# loadBalancers (/docs/reference/api/load-balancers)

> Load balancers on a provider account (DigitalOcean regional and global first). Every call records what the tenant wants and returns at once; the `vps.provider-resources` reconciler converges the provider through `ProviderImpl.loadBalancers`. Reading takes `compute:load-balancers:read`, everything else `compute:load-balancers:manage`, on `provider-load-balancer/{id}`. A load balancer books one `loadBalancers` quota on the pool (no quota row grants none) and bills `vps.load-balancer.hours` from `ready` until deleted.



Load balancers on a provider account (DigitalOcean regional and global first). Every call records what the tenant wants and returns at once; the `vps.provider-resources` reconciler converges the provider through `ProviderImpl.loadBalancers`. Reading takes `compute:load-balancers:read`, everything else `compute:load-balancers:manage`, on `provider-load-balancer/{id}`. A load balancer books one `loadBalancers` quota on the pool (no quota row grants none) and bills `vps.load-balancer.hours` from `ready` until deleted.

What a load balancer reaches is computed from the tenant's own rows and sent to the provider as explicit machine ids, never a tag, so it never reaches another tenant's machine. A `regional` one targets the tenant's instances in its pool and region (`targets: { pool: true }`) or named instances of the tenant (`targets: { instanceIds }`); a `global` one targets the tenant's regional load balancers (`targets: { loadBalancerIds }`). A regional load balancer is in one VPC and the provider balances only to machines in it: it lives on one subnet of a tenant network (`subnetId`, or the subnet its named instances share) and reaches only instances on that subnet, or, without one, on the account's default network and reaches only instances on no tenant network. An instance counts once it has a machine and until it is being deleted. Deleting an instance updates its load balancers at once; one that gains a machine is added by the periodic pass, within five minutes.

All 5 methods are served by @better-compute/server 0.3.0.

| Method              | Kind     | Authorization                                                      | Phase | Status     |
| ------------------- | -------- | ------------------------------------------------------------------ | ----- | ---------- |
| [`create`](#create) | mutation | `compute:load-balancers:manage` @ `compute-provider-load-balancer` | v1.0  | registered |
| [`list`](#list)     | read     | `compute:load-balancers:read` @ `compute-tenant` + items           | v1.0  | registered |
| [`get`](#get)       | read     | `compute:load-balancers:read` @ `compute-provider-load-balancer`   | v1.0  | registered |
| [`update`](#update) | mutation | `compute:load-balancers:manage` @ `compute-provider-load-balancer` | v1.0  | registered |
| [`delete`](#delete) | mutation | `compute:load-balancers:manage` @ `compute-provider-load-balancer` | v1.0  | registered |

## create [#create]

`POST /api/compute/loadBalancers/create`

Makes a load balancer with its `forwarding` rules (1 to 15; an `https` or `http2` entry names a `certificateId` of the tenant on the same account, or an `https` one passes TLS through with `tlsPassthrough`), an optional `healthCheck`, `stickySessions`, `sourceRanges` and `redirectHttpToHttps`, and (global only) the `domains` it serves. It returns `pending`, booking one `loadBalancers`; no room, or no quota row, is `QUOTA_EXCEEDED`. Another tenant's instance is `ACCESS_DENIED`, another region or account `INVALID_INPUT`, named instances on two subnets (or not on `subnetId`) `INVALID_INPUT`, another tenant's subnet `NOT_FOUND`, another tenant's certificate or load balancer `NOT_FOUND`. Named instances are also decided as `compute:instances:update` on each, with the caller's own credential. The provider is asked once the certificates it names are ready. Publishes `providerLoadBalancer.created`, then `providerLoadBalancer.ready` with its `address`, or `providerLoadBalancer.error`.

* **Kind:** mutation
* **Authorization:** `compute:load-balancers:manage` @ `compute-provider-load-balancer`
* **Module:** `vps`
* **Phase:** v1.0 (registered)

**Input**

| Field                            | Type                                          | Required | Constraints                                                        |
| -------------------------------- | --------------------------------------------- | -------- | ------------------------------------------------------------------ |
| `tenantId`                       | string                                        | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`         |
| `projectId`                      | string                                        |          | at most 56 characters; matches `^prj_[0-9a-hjkmnp-tv-z]{26,52}$`   |
| `poolId`                         | string                                        | yes      | at most 57 characters; matches `^pool_[0-9a-hjkmnp-tv-z]{26,52}$`  |
| `name`                           | string                                        | yes      | at most 42 characters; matches `^[a-z]([-a-z0-9]{0,40}[a-z0-9])?$` |
| `description`                    | string                                        |          | at most 256 characters                                             |
| `scope`                          | one of `regional`, `global`                   |          | default `"regional"`                                               |
| `region`                         | string                                        |          | at most 40 characters; matches `^[a-z][a-z0-9-]{0,38}[a-z0-9]$`    |
| `subnetId`                       | string                                        |          | at most 57 characters; matches `^snet_[0-9a-hjkmnp-tv-z]{26,52}$`  |
| `targets`                        | object                                        | yes      |                                                                    |
| `targets.pool`                   | any                                           |          |                                                                    |
| `targets.instanceIds`            | list of string                                |          | 1-100 items                                                        |
| `targets.loadBalancerIds`        | list of string                                |          | 1-100 items                                                        |
| `forwarding`                     | list of object                                | yes      | 1-15 items                                                         |
| `forwarding[].entryProtocol`     | one of `http`, `https`, `http2`, `tcp`, `udp` | yes      |                                                                    |
| `forwarding[].entryPort`         | integer                                       | yes      | 1-65535                                                            |
| `forwarding[].targetProtocol`    | one of `http`, `https`, `http2`, `tcp`, `udp` | yes      |                                                                    |
| `forwarding[].targetPort`        | integer                                       | yes      | 1-65535                                                            |
| `forwarding[].certificateId`     | string                                        |          | at most 58 characters; matches `^pcert_[0-9a-hjkmnp-tv-z]{26,52}$` |
| `forwarding[].tlsPassthrough`    | boolean                                       |          |                                                                    |
| `healthCheck`                    | object                                        |          |                                                                    |
| `healthCheck.protocol`           | one of `http`, `https`, `tcp`                 | yes      |                                                                    |
| `healthCheck.port`               | integer                                       | yes      | 1-65535                                                            |
| `healthCheck.path`               | string                                        |          | at most 255 characters                                             |
| `healthCheck.intervalSeconds`    | integer                                       |          | 3-300                                                              |
| `healthCheck.timeoutSeconds`     | integer                                       |          | 3-300                                                              |
| `healthCheck.healthyThreshold`   | integer                                       |          | 2-10                                                               |
| `healthCheck.unhealthyThreshold` | integer                                       |          | 2-10                                                               |
| `stickySessions`                 | object                                        |          |                                                                    |
| `stickySessions.cookieName`      | string                                        | yes      | at most 40 characters; matches `^[A-Za-z0-9_-]{1,40}$`             |
| `stickySessions.ttlSeconds`      | integer                                       | yes      | 1-604800                                                           |
| `sourceRanges`                   | object                                        |          |                                                                    |
| `sourceRanges.allow`             | list of string                                |          | 0-50 items                                                         |
| `sourceRanges.deny`              | list of string                                |          | 0-50 items                                                         |
| `redirectHttpToHttps`            | boolean                                       |          |                                                                    |
| `domains`                        | list of object                                |          | 0-20 items                                                         |
| `domains[].name`                 | string                                        | yes      | at most 253 characters                                             |
| `domains[].certificateId`        | string                                        |          | at most 58 characters; matches `^pcert_[0-9a-hjkmnp-tv-z]{26,52}$` |
| `idempotencyKey`                 | string                                        | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`         |

## list [#list]

`POST /api/compute/loadBalancers/list`

Returns the tenant's load balancers in the order they were made (at most 1000), optionally of one pool or project. Deleted ones only with `includeDeleted`.

* **Kind:** read
* **Authorization:** `compute:load-balancers:read` @ `compute-tenant` + items
* **Module:** `vps`
* **Phase:** v1.0 (registered)

**Input**

| Field            | Type    | Required | Constraints                                                       |
| ---------------- | ------- | -------- | ----------------------------------------------------------------- |
| `tenantId`       | string  | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`        |
| `poolId`         | string  |          | at most 57 characters; matches `^pool_[0-9a-hjkmnp-tv-z]{26,52}$` |
| `projectId`      | string  |          | at most 56 characters; matches `^prj_[0-9a-hjkmnp-tv-z]{26,52}$`  |
| `includeDeleted` | boolean |          | default `false`                                                   |

## get [#get]

`POST /api/compute/loadBalancers/get`

Returns one load balancer: its settings, targets, `address` (and `addressV6`) once assigned, and its state.

* **Kind:** read
* **Authorization:** `compute:load-balancers:read` @ `compute-provider-load-balancer`
* **Module:** `vps`
* **Phase:** v1.0 (registered)

**Input**

| Field            | Type   | Required | Constraints                                                      |
| ---------------- | ------ | -------- | ---------------------------------------------------------------- |
| `tenantId`       | string | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`       |
| `loadBalancerId` | string | yes      | at most 56 characters; matches `^plb_[0-9a-hjkmnp-tv-z]{26,52}$` |

## update [#update]

`POST /api/compute/loadBalancers/update`

Replaces each part given (`forwarding`, `healthCheck`, `targets`, `stickySessions`, `sourceRanges`, `redirectHttpToHttps`, `domains`) in place and returns it `updating` until the provider has applied it; publishes `providerLoadBalancer.updated` with what `changed`. The scope, region, pool and subnet never change: make another load balancer. Named instances must be on its subnet (or, without one, on no tenant network), else `INVALID_INPUT`.

* **Kind:** mutation
* **Authorization:** `compute:load-balancers:manage` @ `compute-provider-load-balancer`
* **Module:** `vps`
* **Phase:** v1.0 (registered)

**Input**

| Field                            | Type                                          | Required | Constraints                                                        |
| -------------------------------- | --------------------------------------------- | -------- | ------------------------------------------------------------------ |
| `tenantId`                       | string                                        | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`         |
| `loadBalancerId`                 | string                                        | yes      | at most 56 characters; matches `^plb_[0-9a-hjkmnp-tv-z]{26,52}$`   |
| `targets`                        | object                                        |          |                                                                    |
| `targets.pool`                   | any                                           |          |                                                                    |
| `targets.instanceIds`            | list of string                                |          | 1-100 items                                                        |
| `targets.loadBalancerIds`        | list of string                                |          | 1-100 items                                                        |
| `forwarding`                     | list of object                                |          | 1-15 items                                                         |
| `forwarding[].entryProtocol`     | one of `http`, `https`, `http2`, `tcp`, `udp` | yes      |                                                                    |
| `forwarding[].entryPort`         | integer                                       | yes      | 1-65535                                                            |
| `forwarding[].targetProtocol`    | one of `http`, `https`, `http2`, `tcp`, `udp` | yes      |                                                                    |
| `forwarding[].targetPort`        | integer                                       | yes      | 1-65535                                                            |
| `forwarding[].certificateId`     | string                                        |          | at most 58 characters; matches `^pcert_[0-9a-hjkmnp-tv-z]{26,52}$` |
| `forwarding[].tlsPassthrough`    | boolean                                       |          |                                                                    |
| `healthCheck`                    | object                                        |          |                                                                    |
| `healthCheck.protocol`           | one of `http`, `https`, `tcp`                 | yes      |                                                                    |
| `healthCheck.port`               | integer                                       | yes      | 1-65535                                                            |
| `healthCheck.path`               | string                                        |          | at most 255 characters                                             |
| `healthCheck.intervalSeconds`    | integer                                       |          | 3-300                                                              |
| `healthCheck.timeoutSeconds`     | integer                                       |          | 3-300                                                              |
| `healthCheck.healthyThreshold`   | integer                                       |          | 2-10                                                               |
| `healthCheck.unhealthyThreshold` | integer                                       |          | 2-10                                                               |
| `stickySessions`                 | object                                        |          |                                                                    |
| `stickySessions.cookieName`      | string                                        | yes      | at most 40 characters; matches `^[A-Za-z0-9_-]{1,40}$`             |
| `stickySessions.ttlSeconds`      | integer                                       | yes      | 1-604800                                                           |
| `sourceRanges`                   | object                                        |          |                                                                    |
| `sourceRanges.allow`             | list of string                                |          | 0-50 items                                                         |
| `sourceRanges.deny`              | list of string                                |          | 0-50 items                                                         |
| `redirectHttpToHttps`            | boolean                                       |          |                                                                    |
| `domains`                        | list of object                                |          | 0-20 items                                                         |
| `domains[].name`                 | string                                        | yes      | at most 253 characters                                             |
| `domains[].certificateId`        | string                                        |          | at most 58 characters; matches `^pcert_[0-9a-hjkmnp-tv-z]{26,52}$` |

## delete [#delete]

`POST /api/compute/loadBalancers/delete`

Marks the load balancer for deletion and returns it `deleting`; the reconciler deletes it at the provider, refunds its quota and publishes `providerLoadBalancer.deleted`. A regional load balancer a global one of the tenant targets is `INVALID_STATE` (reason `inUse`).

* **Kind:** mutation
* **Authorization:** `compute:load-balancers:manage` @ `compute-provider-load-balancer`
* **Module:** `vps`
* **Phase:** v1.0 (registered)

**Input**

| Field            | Type   | Required | Constraints                                                      |
| ---------------- | ------ | -------- | ---------------------------------------------------------------- |
| `tenantId`       | string | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`       |
| `loadBalancerId` | string | yes      | at most 56 characters; matches `^plb_[0-9a-hjkmnp-tv-z]{26,52}$` |
