# Create an origin pool

> Group the servers that answer for a hostname into a pool, with weights, priorities and health checks.

Source: https://docs.coritan.com/websites/load-balancing/create-an-origin-pool/

In the dashboard:

- /dashboard/websites/…/load-balancing: https://www.coritan.com/dashboard/websites

An origin pool groups the servers that can answer for a hostname, such as the web servers in one data centre, with a health check on each. Create one pool per group of servers, then a [load balancer](/websites/load-balancing/create-a-load-balancer/) that answers a hostname from your pools.

## Before you begin

- The domain's DNS must be hosted on Coritan. If the **Load balancing** tab says **No DNS zone**, [add the domain](/websites/add-an-existing-domain/) first.
- Each origin needs a public IPv4 or IPv6 address. Coritan refuses private and reserved addresses.

## Create a pool

1. In the dashboard, go to [Websites](https://www.coritan.com/dashboard/websites), open the domain and select the **Load balancing** tab.
2. Under **Origin pools**, select **New pool…**.
3. Enter a **Name** that no other pool in the zone has, such as `eu-origins`. A **Description** is optional.
4. Choose the **Algorithm**: **Weighted round-robin** shares queries by weight, and **Failover (by priority)** answers from the origin with the lowest priority number ([Choosing an origin inside a pool](/websites/load-balancing/#choosing-an-origin-inside-a-pool)).
5. If a load balancer will use proximity steering, choose the pool's **Primary location**, the Coritan location nearest its origins.
6. Fill in the first origin under **Origins**:
   - **Address**: the server's public IP address, such as `203.0.113.10`.
   - **Weight**: from 1 to 100, for **Weighted round-robin**.
   - **Priority**: 0 or more, for **Failover (by priority)**. The lowest number answers first.
7. Choose the origin's **Health check** and fill in its fields:
   - **HTTP** or **HTTPS**: the **Path** to ask for, such as `/healthz`, and the **Port** if it is not 80 for HTTP or 443 for HTTPS.
   - **TCP connect**: the **Port** to connect to. Without one, Coritan connects to port 80.
   - **Timeout (s)**: how long the origin has to answer.
8. Select **Add origin** for each other server, and fill it in the same way. Coritan ignores an origin card with no address.
9. Select **Create pool**.

Coritan checks every origin that has a health check once a minute, whatever its **Every (s)** says. The pool's **TTL (s)** and **Session affinity** do not change a load balancer's answers, which use the load balancer's own ([How DNS load balancing works](/websites/load-balancing/#choosing-an-origin-inside-a-pool)).

## Check the origins now

Open the pool's actions menu and select **Run health checks**. Coritan checks every origin in the pool that has a health check, and the badge beside each origin shows its new status.

## Change, turn off or delete a pool

- To change a pool or its origins, open the pool's actions menu and select **Edit pool…**, make the change, then select **Save pool**. To remove an origin, select the × on its card before you save.
- To stop an origin answering without removing it, turn off **Enabled** on its card. The scheduled checks skip a disabled origin.
- To stop every load balancer answering from a pool, turn off its **Enabled** switch in the table, or **Pool enabled** in the pool's dialog. The load balancers skip it until you turn it back on.
- To delete a pool, open its actions menu, select **Delete pool…**, type the pool's name and select **Delete pool**. First remove it from every load balancer that lists it: the dialog names them, and Coritan refuses to delete a pool that one still uses.

> [!CAUTION]
> Deleting a pool deletes its origins and their health checks. It cannot be undone.

## Result

The dashboard confirms `Pool "eu-origins" created.`, and the pool appears under **Origin pools** with its origins and a **Health** badge such as `2 of 2 healthy`. The badge counts the enabled origins that are healthy, or not yet checked.

## Troubleshooting

`Pool saved, but could not save 1 origin.`
: Coritan saved the pool but refused an origin. The dialog stays open and says why for each one; correct the origin and select **Save pool** again.

`health-check target targets a private or reserved network`
: The origin's address is private or reserved, such as `10.0.0.5`. Use the server's public address.

`A members require an IPv4 address` or `AAAA members require an IPv6 address`
: An origin keeps the address family it was created with. To move it from IPv4 to IPv6, remove it and add a new origin.

`Pool name already exists in this zone`
: Another pool in the zone has that name. Choose a different one.

`Pool is referenced by a load balancer; remove it from maps/default/fallback first`
: A load balancer still lists the pool as a default pool, the fallback pool or in a rule. Edit each load balancer the dialog names, remove the pool, then delete it.

`Origin pool limit reached (50)` or `LB member limit reached (20)`
: A zone holds up to 50 pools, and a pool up to 20 origins. Delete what you no longer need, or split the origins across pools.

An origin stays `unhealthy`
: Read why in the origin's `last_error` from the API, such as `HTTP 404` ([With the API](#with-the-api)). The check must get a status from 200 to 399 for its path at the origin's IP address. An **HTTPS** check fails on a certificate that does not include the IP address, so use **HTTP** or **TCP connect** for such an origin.

## Related

- [How DNS load balancing works](/websites/load-balancing/)
- [Create a load balancer](/websites/load-balancing/create-a-load-balancer/)
- [Load balancing reference](/websites/load-balancing/reference/)

## With the API

Create a pool in zone `42`. `algorithm` is `weighted_rr` or `failover`, and `primary_location_code` is a location code such as the ones the **Primary location** list shows:

```bash
curl -X POST https://api.coritan.com/api/v1/dns/zones/42/pools \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "eu-origins", "description": "Web servers in Frankfurt", "algorithm": "weighted_rr"}'
```

The answer is `201` with the pool, which has no origins yet:

```json
{
  "id": 7,
  "zone_id": 42,
  "name": "eu-origins",
  "description": "Web servers in Frankfurt",
  "hostname": null,
  "algorithm": "weighted_rr",
  "ttl": 30,
  "session_affinity": "none",
  "primary_location_code": null,
  "enabled": true,
  "members": [],
  "healthy_members": 0,
  "total_members": 0,
  "created_at": "2026-09-25T09:30:00Z",
  "updated_at": "2026-09-25T09:30:00Z"
}
```

Add an origin to the pool. Set `address_type` to `AAAA` for an IPv6 address; it is `A` when you leave it out. `health_mode` is `none`, `http`, `https` or `tcp`:

```bash
curl -X POST https://api.coritan.com/api/v1/dns/zones/42/pools/7/members \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"address": "203.0.113.10", "weight": 10, "health_mode": "http", "health_path": "/healthz", "health_timeout_s": 5}'
```

The answer is `201` with the origin. Its `health_status` is `unknown` until the first check, or `healthy` when it has no check. `last_check_at` and `last_error` record the latest check.

Run a check now with `POST /api/v1/dns/zones/42/pools/7/members/31/health-check`, which answers with the origin and its new `health_status`.

The other calls:

| Call | What it does |
| --- | --- |
| `GET /api/v1/dns/zones/42/pools` | Lists the zone's pools by name, each with its origins. |
| `GET /api/v1/dns/zones/42/pools/7` | Reads one pool. |
| `PATCH /api/v1/dns/zones/42/pools/7` | Changes the fields you send: `name`, `description`, `algorithm`, `ttl`, `session_affinity`, `primary_location_code` or `enabled`. |
| `DELETE /api/v1/dns/zones/42/pools/7` | Deletes the pool and its origins, and answers `204`. It answers `409` while a load balancer uses the pool. |
| `PATCH /api/v1/dns/zones/42/pools/7/members/31` | Changes the origin fields you send. `address_type` cannot change. |
| `DELETE /api/v1/dns/zones/42/pools/7/members/31` | Removes the origin, and answers `204`. |

The same calls also work under `/api/v1/dns/zones/42/lb-pools`, for older clients. A pool created with a `hostname` also gets a load balancer for that name, with steering off and the pool as its default and fallback pool.

## API

- `GET /api/v1/dns/zones/{zone_id}/pools`: List origin pools (https://docs.coritan.com/api/reference/client/dns/#op-get-api-v1-dns-zones-zone-id-pools)
- `POST /api/v1/dns/zones/{zone_id}/pools`: Create origin pool (https://docs.coritan.com/api/reference/client/dns/#op-post-api-v1-dns-zones-zone-id-pools)
- `GET /api/v1/dns/zones/{zone_id}/pools/{pool_id}`: Get origin pool (https://docs.coritan.com/api/reference/client/dns/#op-get-api-v1-dns-zones-zone-id-pools-pool-id)
- `PATCH /api/v1/dns/zones/{zone_id}/pools/{pool_id}`: Update origin pool (https://docs.coritan.com/api/reference/client/dns/#op-patch-api-v1-dns-zones-zone-id-pools-pool-id)
- `DELETE /api/v1/dns/zones/{zone_id}/pools/{pool_id}`: Delete origin pool (https://docs.coritan.com/api/reference/client/dns/#op-delete-api-v1-dns-zones-zone-id-pools-pool-id)
- `POST /api/v1/dns/zones/{zone_id}/pools/{pool_id}/members`: Create origin member (https://docs.coritan.com/api/reference/client/dns/#op-post-api-v1-dns-zones-zone-id-pools-pool-id-members)
- `PATCH /api/v1/dns/zones/{zone_id}/pools/{pool_id}/members/{member_id}`: Update origin member (https://docs.coritan.com/api/reference/client/dns/#op-patch-api-v1-dns-zones-zone-id-pools-pool-id-members-member-id)
- `DELETE /api/v1/dns/zones/{zone_id}/pools/{pool_id}/members/{member_id}`: Delete origin member (https://docs.coritan.com/api/reference/client/dns/#op-delete-api-v1-dns-zones-zone-id-pools-pool-id-members-member-id)
- `POST /api/v1/dns/zones/{zone_id}/pools/{pool_id}/members/{member_id}/health-check`: Health check origin member (https://docs.coritan.com/api/reference/client/dns/#op-post-api-v1-dns-zones-zone-id-pools-pool-id-members-member-id-health-check)
- `GET /api/v1/dns/zones/{zone_id}/lb-pools`: List LB pools (https://docs.coritan.com/api/reference/client/dns/#op-get-api-v1-dns-zones-zone-id-lb-pools)
- `POST /api/v1/dns/zones/{zone_id}/lb-pools`: Create LB pool (https://docs.coritan.com/api/reference/client/dns/#op-post-api-v1-dns-zones-zone-id-lb-pools)
- `GET /api/v1/dns/zones/{zone_id}/lb-pools/{pool_id}`: Get LB pool (https://docs.coritan.com/api/reference/client/dns/#op-get-api-v1-dns-zones-zone-id-lb-pools-pool-id)
- `PATCH /api/v1/dns/zones/{zone_id}/lb-pools/{pool_id}`: Update LB pool (https://docs.coritan.com/api/reference/client/dns/#op-patch-api-v1-dns-zones-zone-id-lb-pools-pool-id)
- `DELETE /api/v1/dns/zones/{zone_id}/lb-pools/{pool_id}`: Delete LB pool (https://docs.coritan.com/api/reference/client/dns/#op-delete-api-v1-dns-zones-zone-id-lb-pools-pool-id)
- `POST /api/v1/dns/zones/{zone_id}/lb-pools/{pool_id}/members`: Create LB member (https://docs.coritan.com/api/reference/client/dns/#op-post-api-v1-dns-zones-zone-id-lb-pools-pool-id-members)
- `PATCH /api/v1/dns/zones/{zone_id}/lb-pools/{pool_id}/members/{member_id}`: Update LB member (https://docs.coritan.com/api/reference/client/dns/#op-patch-api-v1-dns-zones-zone-id-lb-pools-pool-id-members-member-id)
- `DELETE /api/v1/dns/zones/{zone_id}/lb-pools/{pool_id}/members/{member_id}`: Delete LB member (https://docs.coritan.com/api/reference/client/dns/#op-delete-api-v1-dns-zones-zone-id-lb-pools-pool-id-members-member-id)
- `POST /api/v1/dns/zones/{zone_id}/lb-pools/{pool_id}/members/{member_id}/health-check`: Health check LB member (https://docs.coritan.com/api/reference/client/dns/#op-post-api-v1-dns-zones-zone-id-lb-pools-pool-id-members-member-id-health-check)
