# Load balancing reference

> Fields, limits, region codes and error messages for origin pools and load balancers.

Source: https://docs.coritan.com/websites/load-balancing/reference/

The fields below appear in the dashboard's dialogs on a domain's **Load balancing** tab and in the API's request and response bodies. The limits are in [How DNS load balancing works](/websites/load-balancing/#limits).

## Origin pool fields

| Dashboard | API field | Values |
| --- | --- | --- |
| **Name** | `name` | 1–100 characters, unique in the zone |
| **Description** | `description` | Optional text |
| **Algorithm** | `algorithm` | `weighted_rr` (**Weighted round-robin**, the default) or `failover` (**Failover (by priority)**) |
| **TTL (s)** | `ttl` | 5–3,600 seconds, 30 by default. Load balancers answer with their own TTL. |
| **Session affinity** | `session_affinity` | `none` or `client_ip`. Load balancers use their own. |
| **Primary location** | `primary_location_code` | A Coritan location code, or `null` for **Not set** |
| **Pool enabled** | `enabled` | `true` by default. A disabled pool is skipped. |

A pool in the API also has `id`, `zone_id`, `members` (its origins), `healthy_members`, `total_members`, `created_at`, `updated_at` and `hostname`, which older clients send to create a load balancer with the pool.

## Origin fields

| Dashboard | API field | Values |
| --- | --- | --- |
| **Address** | `address` | A public IPv4 or IPv6 address |
| None; the dashboard reads it from the address | `address_type` | `A` (the default) or `AAAA`. It cannot change after the origin is created. |
| **Weight** | `weight` | 1–100, 1 by default |
| **Priority** | `priority` | 0 or more, 0 by default. The lowest number answers first. |
| **Enabled** | `enabled` | `true` by default |
| **Health check** | `health_mode` | `none` (**None**, the default), `http` (**HTTP**), `https` (**HTTPS**) or `tcp` (**TCP connect**) |
| **Path** | `health_path` | `/` by default |
| **Port** | `health_port` | 1–65,535. Empty means 443 for `https` and 80 otherwise. |
| **Every (s)** | `health_interval_s` | 30 by default. Coritan checks once a minute whatever it says. |
| **Timeout (s)** | `health_timeout_s` | 5 by default |

The API also returns `id`, `pool_id`, `health_status`, `last_check_at`, `last_error` (why the last check failed, such as `HTTP 503`), `created_at` and `updated_at`.

## Health statuses

`healthy`
: The last check passed, or the origin has no check.

`unhealthy`
: The last check failed. Load balancers skip the origin while another origin can answer.

`unknown`
: The origin has not been checked yet. Load balancers treat it as healthy.

## Load balancer fields

| Dashboard | API field | Values |
| --- | --- | --- |
| **Name** | `name` | 1–100 characters |
| **Hostname** | `hostname` | `@` for the domain, or a name under the zone such as `api` |
| **TTL (s)** | `ttl` | 5–3,600 seconds, 30 by default |
| **Session affinity** | `session_affinity` | `none` (**None**, the default) or `client_ip` (**By client IP**) |
| **Steering** | `steering_policy` | `off` (**Off**, the default), `random` (**Random**), `geo` (**Geographic**) or `proximity` (**Proximity**) |
| **Locate the client by** | `location_strategy` | `pop` (**Answering PoP**, the default) or `resolver_ip` (**Resolver IP**) |
| **Default pools** | `default_pools` | Pool IDs, in the order to try them |
| **Fallback pool** | `fallback_pool_id` | A pool ID, or `null` for **None** |
| **By region** | `region_pools` | Region codes, each with a list of pool IDs, such as `{"WEU": [7]}` |
| **By country** | `country_pools` | Two-letter country codes, each with a list of pool IDs, such as `{"DE": [7]}` |
| **By PoP** | `location_pools` | PoP codes, each with a list of pool IDs |
| **Load balancer enabled** | `enabled` | `true` by default |

The dashboard saves the rules only for **Geographic** steering. Saving a load balancer with any other **Steering** deletes its rules.

## Region codes

| Code | Region |
| --- | --- |
| `WNAM` | Western North America |
| `ENAM` | Eastern North America |
| `WEU` | Western Europe |
| `EEU` | Eastern Europe |
| `SEAS` | Southeast Asia |
| `NEAS` | Northeast Asia |
| `SAS` | Southern Asia |
| `ME` | Middle East |
| `AF` | Africa |
| `OC` | Oceania |
| `SAM` | South America |

When Coritan places a client by its resolver's IP address, it puts the United States in `ENAM` and Canada in `WNAM`. To split North America by coast, use **By PoP** rules with **Answering PoP**.

List the regions with the countries in each:

```bash
curl https://api.coritan.com/api/v1/dns/lb-regions \
  -H "Authorization: Bearer $CORITAN_TOKEN"
```

```json
[
  {"code": "WNAM", "name": "Western North America", "sort_order": 10, "countries": ["US", "CA", "MX"]},
  {"code": "ENAM", "name": "Eastern North America", "sort_order": 20, "countries": ["US", "CA"]}
]
```

## Preview results

**Preview answers** in the dashboard and `POST /api/v1/dns/zones/{zone_id}/load-balancers/{lb_id}/preview` in the API report how the answer was chosen.

| `cascade_hit` | **Chosen by** shows | Meaning |
| --- | --- | --- |
| `location` | `PoP rule` | A **By PoP** rule matched. |
| `country` | `Country rule` | A **By country** rule matched. |
| `region` | `Region rule` | A **By region** rule matched. |
| `default` | `Default pools` | The default pools answered. |
| `fallback` | `Fallback pool` | The fallback pool answered. |
| `proximity` | `Nearest pool` | Proximity steering ranked the pools. |
| `serve_last` | `Last healthy answer` | No pool had a healthy origin, and Coritan answered with an enabled origin anyway. |

`reason` is one of:

`ok`
: A healthy origin answered.

`all_unhealthy_serve_last`
: No origin was healthy, and an enabled origin answered anyway.

`all_unhealthy`
: No origin was healthy, and the answer is `SERVFAIL` (`servfail` is `true`).

`no_members`
: No pool in the order has an enabled origin of the type asked for.

`load_balancer_disabled`
: The load balancer is off.

`context.source` says how the preview placed the client: `pop` for a PoP you chose, `resolver_ip` for an address you entered, and `override` when you gave neither.

## Errors

| Message | Status | Cause |
| --- | --- | --- |
| `Origin pool not found`, `LB member not found`, `Load balancer not found` | 404 | The ID is not in this zone. |
| `Origin pool limit reached (50)`, `LB member limit reached (20)`, `Load balancer limit reached (50)` | 403 | The zone or pool is full. |
| `Steering entry limit reached (200)` | 403 | The load balancer lists more than 200 pool entries across its default pools and rules. |
| `Pool name already exists in this zone`, `Pool name already exists` | 409 | Another pool in the zone has that name. |
| `A load balancer already owns this hostname` | 409 | Another load balancer answers for the name. |
| `Hostname already has A/AAAA/CNAME records; remove them before creating a load balancer` | 409 | The name has records a load balancer would replace. |
| `Pool is referenced by a load balancer; remove it from maps/default/fallback first` | 409 | A load balancer still lists the pool. |
| `Invalid IP address: …` | 422 | The origin's address is not an IP address. |
| `A members require an IPv4 address`, `AAAA members require an IPv6 address` | 422 | The address does not match `address_type`. |
| `health-check target targets a private or reserved network` | 422 | The origin's address is private or reserved. |
| `Unknown region code: …` | 422 | A `region_pools` key is not in the region list. |
| `Unknown pool ids for this zone: […]` | 422 | A pool ID in the request belongs to no pool in this zone. |

A value outside its range, such as a `weight` of `0`, gets a `422` validation error that names the field.

## API

- `GET /api/v1/dns/lb-regions`: List DNS LB regions (https://docs.coritan.com/api/reference/client/dns/#op-get-api-v1-dns-lb-regions)
