Skip to main content
A load balancer accepts connections on one or more listeners and forwards them to a target group. It runs on compute instances the platform operates for you — the replicas — inside your own VPC subnet, so it reaches your backends over private addresses and is reachable from the internet only if you give it a floating IP. The service is regional: https://loadbalancer.sa-saopaulo-1.basaltic.sh.

application

Layer 7. Hosts http and https listeners, routes on host, path, header, query and method, and terminates TLS.

network

Layer 4. Hosts tcp and udp listeners and forwards streams to a single target group.
type is fixed at create. There is no patch that converts one into the other — create a second load balancer and move the address.

Create one

The subnet, the flavor family, and the security group requirement that trips people up.

Give it an address

The private VIP, the floating IP you can only attach at create, and the hostname you point a name at.

Listeners and rules

Protocols, exposure, certificates, and how a request picks a target group.

Target groups

Targets, health checks, stickiness, and PROXY protocol.

Replicas and resizing

Scaling, the surge-first flavor roll, and how to watch it.

Troubleshooting

Active but unreachable, targets stuck at initial, a resize that stalls.

Creating a load balancer

required, at least one
The replicas inherit these on every NIC, and a NIC in no security group accepts nothing. A load balancer without one would still provision, still take a floating IP and still report active — while answering no one. The create is refused instead. The listener port has to be opened by a security group listed here, or the load balancer is unreachable on it.
loadbalancer-family only
The replicas are platform-operated and priced accordingly, so a general or database flavor is rejected with the flavor’s family named in the error.
must belong to vpc_id
The replicas get NICs here and the virtual IP is reserved out of this subnet’s range.
1–10, default 1
Pick at least 2 for HA. See replicas.
The response is 201 with the load balancer in provisioning. It flips to active on the first replica whose proxy reports ready — the replicas boot, install their software and pull their configuration, so expect a few minutes.
key_names is not a tenant feature. The replicas run the platform’s own proxy software, and SSH into them is reserved for operator break-glass; the field is refused for any other account. You reach a load balancer over its address, never over SSH.

How a load balancer gets its address

Every load balancer holds a private virtual IP (vip_v4) reserved from its subnet at create. That address is what internal clients in the VPC use, and it is the only address a load balancer has unless you give it one more. For public traffic you attach a floating IP:
floating_ip_id is accepted only on create. PATCH /v1/load-balancers/{id} takes name, replica_count, flavor_id and tags — not an address. A load balancer created without one cannot be made internet-facing later; create a new one with the floating IP and move traffic to it.
The attach is refused unless the load balancer’s subnet already routes 0.0.0.0/0 to an internet gateway. Reply traffic leaves by that subnet’s route table, so without the default route the address would be handed back unreachable. Add the gateway and the route first — see networking.
On an internet-facing load balancer in a dual-stack subnet you also get public_vip_v6, a public IPv6 address. IPv6 has no NAT, so that address is the public ingress rather than a translation of something else. It is allocated best-effort at create: a single-stack subnet simply leaves the load balancer public over IPv4 only. The vip_v6 field is reserved and is not populated today.

Pointing a name at it

The response carries dns_name, a hostname published for you in a shared regional zone, shaped {name}.{account}.lb.<region>.<base-domain>. It resolves to the floating IP on an internet-facing load balancer and to the private VIP otherwise.
Read dns_name from the response rather than assembling it. It is empty in a region where the convenience zone is not configured — the VIP and floating IP stay authoritative either way.
Renaming the load balancer republishes the record under the new name and retires the old one, so anything pointing at the old hostname stops resolving. For your own domain, publish a CNAME to dns_name — or an A record to the floating IP if you need an apex — with DNS.

Listeners

A listener binds one protocol and port on the load balancer. The pair has to be unique — a second listener on the same protocol and port is refused — so a network load balancer can serve tcp and udp on the same port number, but never two tcp listeners on one.
Mixing them is rejected at create with the reason named. Protocol values are lowercase, which is the platform convention for enums we define; values that come from a standard keep that standard’s own casing — an HTTP method in a rule condition is GET, not get.

Exposure

exposure picks which of the load balancer’s addresses the listener binds.
the subnet VIP
Reachable from inside the VPC only.
the floating IP
Reachable from the internet only.
default when a floating IP is attached
Binds the VIP and the floating IP.
The default adapts to the load balancer: both when it carries a floating IP, private_only when it does not, because with no public address there is no public traffic for a listener to see. Asking for public_only or both on a load balancer with no floating IP is rejected up front rather than accepted and silently kept private.
A public_only listener stops being served entirely if the floating IP goes away — it has no address left to bind. A both listener keeps serving privately. Patch exposure to private_only if you meant to keep it internal.

Certificates on an HTTPS listener

An HTTPS listener needs at least one certificate, named by CRN. No key material is ever sent to this API: the listener stores a reference, and the replicas fetch the material from the certificate service under their own identity. A listener can hold several certificates and picks one per connection by matching the client’s SNI against each certificate’s SANs. The one flagged is_default is the fallback for a client whose SNI matches nothing, or that sends none at all.
Setting a new default demotes the previous one in the same transaction, so a listener always has exactly one.
Detaching is refused in two cases: removing the last certificate from an HTTPS listener, and removing the current default while other certificates are still attached. Promote a replacement first, then detach.
A certificate CRN ends in certificate/<name>, so the slash must be percent-encoded as %2F when the CRN sits in a path segment. Sent raw it addresses a different route that does not exist.
Certificates the platform renews are picked up on their own — a reissue changes the fingerprint the replicas track and they re-fetch. To force a re-check of an already-attached certificate, patch the listener with its CRN. Attaching and detaching also re-scope the replicas’ access so it covers exactly the certificates currently attached, and nothing else.

Default target group

default_target_group_id is where a request goes when no rule matches. On a tcp or udp listener it is the only destination — rules do not apply at layer 4 — so an L4 listener without one has nowhere to send traffic. An HTTP or HTTPS listener with no default and no matching rule answers 503 with the body no default target group. Set it, or clear it deliberately with clear_default_target_group: true once your rules cover everything you serve.

Routing rules

Rules exist on http and https listeners only; creating one on an L4 listener is refused. Each rule has a priority, a list of conditions, and a target group.
Rules are evaluated in ascending priority and the first match wins; priority is 1..50000 and unique per listener. Every condition on a rule has to match — the list is an AND.
Give each condition a single value. values is an array, but the data plane matches on the first entry and ignores the rest. Express alternatives with glob or regex, or write one rule per value.
A header or query condition without name is rejected, and so is a regex value that does not compile as RE2. That strictness is deliberate: a load balancer’s configuration is built in one pass, so a single untranslatable condition would stop every replica loading any configuration at all — including replacements a resize is waiting on. Refusing the write costs you one error instead of an outage. Updating a rule is a full replace: send priority, conditions and target_group_id together, the same shape as create.
Delete a rule through its listener — DELETE /v1/load-balancers/{id}/listeners/{listener_id}/rules/{rule_id}. The listener-less form still works for clients already on it, but it has to scan the load balancer’s listeners to prove the rule belongs there.

Target groups

A target group is the named set of backends a listener or rule forwards to. It is an account-scoped resource of its own, not a child of a load balancer, so one group can back several listeners — which is what makes a blue/green swap a matter of repointing a rule.
http | https | tcp | udp
Must match the protocol of the listener that points at it.
ip | instance (default ip)
What target_ref means on each attached target.
static | pool (default static)
static uses the targets you attach. pool takes its backends from a compute instance pool named by instance_pool_id, so scaling the pool moves the backend set with it — and attaching a target by hand is refused with a 409, because a row nothing would ever route to is worse than an error. A pool-mode group is forced to target_type: instance.
1–65535
The default port for targets in the group. A target can override it.
Deleting a group while a listener default or a rule still references it is a 409 — repoint or delete the reference first. The number of listeners per load balancer, target groups per load balancer and targets per group are account quotas; exceeding one is refused at the write.
target_type: function is accepted on a group, but attaching a target to it is refused: the function runtime is not available yet, so the group has no way to resolve a backend.

Attaching targets

target_ref is an IP address on an ip group and a compute instance id on an instance group. An instance reference stays unresolved in the row and becomes an address at configuration time, so an instance whose NIC address changes needs no update here. The instance has to exist in your account — see compute. Addresses are stored canonically, so the spelling you read back may differ from the one you sent, and two spellings of the same endpoint are recognised as the duplicate they are.
An ip target has to be a routable unicast address. Loopback, link-local, multicast and unspecified addresses are rejected. This is a security boundary, not tidiness: link-local carries the instance metadata endpoint and loopback is the replica’s own administrative socket. Both are reachable from a replica, so without the check a listener would proxy them straight out to the internet. The IPv4-mapped IPv6 form is rejected too — send the dotted IPv4 form.
Detaching a target removes it immediately.

Health checks

The data plane probes each target and reports what it sees. Set the knobs per group, at create or with a patch:
protocol defaults to the group’s own. Probing over HTTP on a tcp group is supported and common — a backend that speaks a binary protocol can still serve a health page. path defaults to / for http and https; tcp and udp checks are connect-only and ignore it. The thresholds are consecutive results: three failures in a row to go unhealthy, three successes to come back.
health_check.matcher and health_check.port are accepted and stored, but are not applied to the probe today. A probe hits the target’s own port. Leave them unset rather than expecting them to change anything.
Read the result on each target:

Session affinity

By default every request is balanced independently. Turn on stickiness per target group:
Both modes hash consistently, so adding or losing a backend moves only the clients that backend was serving instead of reshuffling everyone.

Seeing the real client

An http or https target group already gets the client’s address in X-Forwarded-For, and any X-Forwarded-For the client sent itself is not trusted — the load balancer is the edge, so nothing upstream of it counts. For tcp and udp groups, or backends that prefer a framed envelope, set proxy_protocol: true and upstream connections are wrapped in a PROXY v2 header carrying the original client address and port.

Replicas

replica_count is how many instances serve your traffic. One is enough to work; two or more is what survives losing one.
Replicas are managed instances, so GET /v1/instances does not return them by design. This endpoint is the only window onto them.
Each entry carries instance_id, replica_index, the flavor_id it actually booted on, and a liveness view refreshed on every health report: The load balancer itself goes active on the first replica to report healthy, and drops to error only when every replica has gone silent past the staleness window — one missed report is not enough. It returns to active as soon as any replica resumes.

Scaling

Scale-out provisions the new replicas; scale-in removes the highest-indexed ones. Range is 1..10.

Changing the flavor

A running instance cannot change size in place, so a resize records the new size and returns — the replicas already up are replaced one at a time in the background, over the following minutes.
The pool grows before it shrinks. An extra replica comes up on the new flavor and starts serving before any replica on the old one is retired, so the number serving never drops below replica_count — including at replica_count: 1, where retiring first would mean serving nothing while the replacement booted. When the last old replica goes, the pool comes back down.
Watch it on GET /v1/load-balancers/{id}/replicas. A replica has been replaced when its instance_id changes, and the resize is done when every flavor_id there matches the load balancer’s. Seeing one more replica listed than replica_count part-way through is the surge keeping your capacity up, not a replica leaking — it goes away when the last old one does.
Two things worth knowing:
  • Nothing is retired until everything is healthy. The roll waits for the pool to be complete with every replica reporting and its proxy up. A replacement that never comes up healthy stalls the resize with the load balancer whole, rather than walking it down one replica per pass.
  • A load balancer already at 10 replicas has nowhere to grow. There the replicas are replaced in place and nine serve while each replacement boots.
A resize is rejected up front if your account lacks the compute quota for the replacement replica, so it cannot half-apply and leave the load balancer short.

Deleting

Answers 202. The load balancer moves to deleting and stays readable while its address reservation, replicas and internal state are released, with the record removed last. Poll until it answers 404 rather than treating the 202 as proof it is gone. Repeating the delete is safe.

Statuses

Limits and naming

unique per account
Starts with a letter, then letters, digits, ., _ or -, up to 127 characters. It appears in the CRN, so it has to be URL-safe.
name-based
A load balancer’s CRN ends in loadbalancer/<name> and a target group’s in target-group/<name>. Because the CRN carries the name, an IAM policy can wildcard a naming convention rather than listing ids. Take the exact string from the resource’s crn field rather than assembling it.
1–10
Both at create and on a patch.
1–50000
Unique per listener.
Listeners per load balancer, target groups per load balancer and targets per target group are account quotas rather than fixed numbers. List operations page with limit and marker; page until meta.has_more is false rather than until a page looks short. Creates accept an Idempotency-Key header, which makes a retry return the original outcome instead of a duplicate.

Troubleshooting

The most common cause is that no security group on the replicas opens the listener port. security_group_ids is set at create and cannot be patched on the load balancer — change the rules inside the security groups you already attached, or recreate with the right set. See networking.The second cause is a listener whose exposure is private_only when you expected public, or public_only on a load balancer whose floating IP is gone — a public_only listener with no public address is not served at all.
The load balancer’s subnet has no 0.0.0.0/0 route to an internet gateway. Reply traffic leaves by that route table, so the address would be unreachable. Attach an internet gateway to the VPC and add the default route, then create the load balancer with floating_ip_id — remember it is a create-time field only.
initial means no probe has succeeded yet. Check, in order: the backend is listening on the group’s port (or the target’s override); the backend’s own security group allows the replicas’ subnet; and, for an HTTP check, that path returns a success status. Remember the probe hits the target’s own port — health_check.port is not applied today.
Three things to check. Rules run in ascending priority and the first match wins, so a broad low-numbered rule shadows the specific ones under it. Every condition on a rule must match — the list is an AND, not an OR. And a condition matches on the first entry of values; extra entries are ignored, so express alternatives with glob or regex.With no rule matching, the request goes to the listener’s default_target_group_id, or gets a 503 reading no default target group if there is none.
Two removals are refused: the last certificate on an HTTPS listener, and the certificate currently flagged is_default while others remain. Attach or promote a replacement as the default first — that demotes the old one in the same transaction — then detach.If the request 404s or errors on the path itself, the CRN’s slash was sent raw. Percent-encode it as %2F.
The roll advances by one replica at a time and will not retire anything while any replica is unhealthy or still coming up. So a stalled resize usually means a replacement that never came up healthy — check GET /v1/load-balancers/{id}/replicas for one sitting at initializing or unhealthy. The load balancer keeps serving on the replicas it has while this is true, which is the point.Seeing one replica more than replica_count mid-roll is expected.
A listener’s default_target_group_id or a rule’s target_group_id still points at it. Repoint or delete the reference, then delete the group.

Next

Certificates

Issuing the certificates a listener serves, and how renewal reaches the load balancer.

Networking

VPCs, subnets, security groups, internet gateways and floating IPs.

Compute

Instances and instance pools — the backends a target group points at.

DNS

Pointing your own domain at a load balancer.