Load Balancer
Add a backend to a listener
Section titled “Add a backend to a listener”POST /v1/load-balancers/{id}/backends · scope lb:write · reversible · idempotent
A shortcut over PUT /listeners for the common case of adding a machine. It revalidates and applies the full configuration, so it inherits the same guarantee: either the backend ends up receiving traffic, or nothing changed.
curl https://api.truo.cloud/v1/load-balancers/svc_10432/backends \ -X POST \ -H "Authorization: Bearer $TRUO_TOKEN" \ -H "Content-Type: application/json" \ -d '{"listener":"<listener>","ip":"<ip>","port":1}'truo lb backend add svc_10432await truo.lb.backends.create("svc_10432", {"listener":"<listener>","ip":"<ip>","port":1});truo_lb({ "action": "backend_create", "id": "svc_10432"})operationId: lb.backends.create
Remove a backend from a listener
Section titled “Remove a backend from a listener”DELETE /v1/load-balancers/{id}/backends/{listener}/{ip}/{port} · scope lb:write · destructive — cannot be undone · idempotent
The three values identifying the backend go in the path. The upstream expects them in the body of a DELETE, which proxies and CDNs discard and several HTTP clients refuse to send; the body is built on this side.
A listener cannot be left without backends. Removing the last one returns 400 validation_failed: to remove the whole listener, use PUT /listeners without it.
curl https://api.truo.cloud/v1/load-balancers/svc_10432/backends/web/10.0.0.5/8080 \ -X DELETE \ -H "Authorization: Bearer $TRUO_TOKEN"truo lb backend remove svc_10432 web 10.0.0.5 8080await truo.lb.backends.delete("svc_10432", "web", "10.0.0.5", "8080");truo_lb({ "action": "backend_delete", "id": "svc_10432", "listener": "web", "ip": "10.0.0.5", "port": "8080"})operationId: lb.backends.delete
List the backends
Section titled “List the backends”GET /v1/load-balancers/{id}/backends · scope lb:read
The backends of every listener, flattened, each with the listener it belongs to. It is a view over the same configuration that GET /listeners returns.
curl https://api.truo.cloud/v1/load-balancers/svc_10432/backends \ -H "Authorization: Bearer $TRUO_TOKEN"truo lb backend list svc_10432await truo.lb.backends.list("svc_10432");truo_lb({ "action": "backend_list", "id": "svc_10432"})operationId: lb.backends.list
Get a load balancer with its live state
Section titled “Get a load balancer with its live state”GET /v1/load-balancers/{id} · scope lb:read
Queries the control plane, which in turn probes the balancer. If it does not respond, the state fields come back null instead of failing.
curl https://api.truo.cloud/v1/load-balancers/svc_10432 \ -H "Authorization: Bearer $TRUO_TOKEN"truo lb get svc_10432await truo.lb.instances.get("svc_10432");truo_lb({ "action": "get", "id": "svc_10432"})operationId: lb.instances.get
List load balancers
Section titled “List load balancers”GET /v1/load-balancers · scope lb:read
Served from the database, without querying the control plane: provisioning_state, healthy, and listener_count come back null. Fetching them would cost one call per page item.
A page can come back with fewer items than limit even when more exist: every control plane product shares the same provisioning module, so the family filter can only be applied after reading the page. has_more remains the correct signal for whether anything is left to fetch.
curl https://api.truo.cloud/v1/load-balancers \ -H "Authorization: Bearer $TRUO_TOKEN"truo lb listawait truo.lb.instances.list();truo_lb({ "action": "list"})operationId: lb.instances.list
List the listeners
Section titled “List the listeners”GET /v1/load-balancers/{id}/listeners · scope lb:read
The balancer’s full configuration, including each listener’s backends. It is what you read, modify, and send back in PUT.
curl https://api.truo.cloud/v1/load-balancers/svc_10432/listeners \ -H "Authorization: Bearer $TRUO_TOKEN"truo lb listener list svc_10432await truo.lb.listeners.list("svc_10432");truo_lb({ "action": "listener_list", "id": "svc_10432"})operationId: lb.listeners.list
Replace the listener configuration
Section titled “Replace the listener configuration”PUT /v1/load-balancers/{id}/listeners · scope lb:write · destructive — cannot be undone · idempotent
Replaces the entire set: listeners missing from listeners are deleted, along with their backends. Sending [] leaves the balancer with nothing listening and cuts traffic. Read GET /listeners, modify, and send everything back.
The change is applied within the call: by the time this returns, the new configuration is already serving traffic. If the resulting configuration is invalid, nothing is applied and the response is 400 validation_failed — the service is never left half-configured.
curl https://api.truo.cloud/v1/load-balancers/svc_10432/listeners \ -X PUT \ -H "Authorization: Bearer $TRUO_TOKEN" \ -H "Content-Type: application/json" \ -d '{"listeners":[]}'truo lb listener apply svc_10432await truo.lb.listeners.replace("svc_10432", {"listeners":[]});truo_lb({ "action": "listener_replace", "id": "svc_10432"})operationId: lb.listeners.replace
Get per-listener state and traffic
Section titled “Get per-listener state and traffic”GET /v1/load-balancers/{id}/stats · scope lb:read
A point-in-time snapshot: current connections and bytes accumulated since the balancer’s last start, plus each backend’s health from the latest probe. For the series over time, use GET /v1/load-balancers/{id}/stats/history.
If the balancer does not answer the probe, the listeners still appear —they come from the stored configuration— with state: unknown and zeroed counters. A listener that exists but does not respond and one that exists with no traffic cannot be told apart by the counters: check state.
curl https://api.truo.cloud/v1/load-balancers/svc_10432/stats \ -H "Authorization: Bearer $TRUO_TOKEN"truo lb stats svc_10432await truo.lb.stats.get("svc_10432");truo_lb({ "action": "stats", "id": "svc_10432"})operationId: lb.stats.get
Get the traffic history
Section titled “Get the traffic history”GET /v1/load-balancers/{id}/stats/history · scope lb:read
Fixed-size buckets for the requested window: new connections per second, bytes in and out per second, average and peak concurrent connections, and the lowest number of healthy backends. total adds every listener; listeners has the same series per listener.
The balancer is sampled once a minute and samples are kept 14 days. Every bucket of the window is returned; a bucket with no samples (before the service existed, or while it was unreachable) has null fields, which is a gap and not a zero. Rates come from cumulative counters, so a configuration change does not produce a spike or a negative value.
curl https://api.truo.cloud/v1/load-balancers/svc_10432/stats/history \ -H "Authorization: Bearer $TRUO_TOKEN"truo lb history svc_10432await truo.lb.stats.history("svc_10432");truo_lb({ "action": "stats_history", "id": "svc_10432"})operationId: lb.stats.history