Canadian cloud in Montréal · VMs from 8.50 CAD/month

API

Load balancers

Spread traffic across your machines: pools, listeners, routing by hostname and path, automatic certificates.

A load balancer receives traffic on its own public IPv4 and IPv6 address and spreads it across machines of one of your private networks, over TCP or HTTP(S). It is a managed service: FFxF runs it, keeps it up to date and obtains its Let's Encrypt certificates; you only describe where traffic goes.

How it fits together

  • A pool groups the machines that serve the same thing (frontend, backend, db). Each target is a machine of the private network and a port. Unhealthy targets stop getting traffic.
  • A listener is an entry port on the load balancer's address, http, https or tcp, with a default pool.
  • On HTTP(S) listeners, rules send a hostname and/or a path prefix to another pool: app.example.com to frontend, app.example.com/api/ or api.example.com to backend.

Targets keep their private address: they need no public IP, and their own firewalls can close 80 and 443 to the Internet, since the private network is never filtered.

Create a load balancer

bash
curl -s -X POST https://api.ffxf.net/v1/load-balancers \
     -H "Authorization: Bearer $FFXF_TOKEN" \
     -H "Idempotency-Key: $(uuidgen)" \
     -H "Content-Type: application/json" \
     -d '{"name": "website", "vpc": 12}'
bash
{ "data": { "id": 4, "name": "website", "status": "pending", "vpc": 12, "ipv4": "23.159.52.40", "ipv6": "2602:f3a4:0:100::40", "pools": [], "listeners": [] } }

Billing starts now, by the hour, like a machine (the account needs 24 hours of credit). The load balancer is ready within a few minutes: status goes from pending to active. You can set up pools and listeners meanwhile; they apply as soon as it is ready.

Pools and targets

bash
curl -s -X POST https://api.ffxf.net/v1/load-balancers/4/pools \
     -H "Authorization: Bearer $FFXF_TOKEN" -H "Content-Type: application/json" \
     -d '{"name": "frontend", "protocol": "http", "health_type": "http", "health_path": "/health"}'

curl -s -X PUT https://api.ffxf.net/v1/load-balancers/4/pools/9/targets \
     -H "Authorization: Bearer $FFXF_TOKEN" -H "Content-Type: application/json" \
     -d '{"targets": [{"vm": 4821, "port": 3000}, {"vm": 4822, "port": 3000}]}'

PUT …/targets replaces the whole list: describe the state you want and replay it as often as you like; a target you keep keeps its health. A machine is named by its id, as in GET /vms, and must be in the load balancer's private network. An http pool serves http and https listeners; a tcp pool serves tcp listeners and can send the PROXY protocol v2 (send_proxy).

Health checks run every 5 seconds by default: a TCP connection, or for HTTP pools a GET on health_path where any 2xx or 3xx is healthy. Three failures take a target out, two successes bring it back.

Listeners

bash
curl -s -X POST https://api.ffxf.net/v1/load-balancers/4/listeners \
     -H "Authorization: Bearer $FFXF_TOKEN" -H "Content-Type: application/json" \
     -d '{"port": 443, "protocol": "https", "default_pool": 9, "redirect_https": true}'

redirect_https makes port 80 redirect to this listener. HTTP requests carry X-Forwarded-For, X-Forwarded-Proto and X-Forwarded-Port. Ports 22 and 8402 are reserved; with an HTTPS listener, port 80 can only be HTTP. A tcp listener forwards everything to its default pool without reading it.

Routing rules

bash
curl -s -X PUT https://api.ffxf.net/v1/load-balancers/4/listeners/15/rules \
     -H "Authorization: Bearer $FFXF_TOKEN" -H "Content-Type: application/json" \
     -d '{"rules": [
           {"hostname": "app.example.com", "pool": 9},
           {"hostname": "app.example.com", "path_prefix": "/api/", "pool": 10},
           {"hostname": "api.example.com", "pool": 10}
         ]}'

The list is replaced as a whole. Whatever the order you send, rules are evaluated most specific first, and the first match wins:

RankRuleExample
1Exact hostname and path (longest path first)app.example.com + /api/
2Exact hostnameapp.example.com
3Wildcard and path*.example.com + /static/
4Wildcard*.example.com
5Path only/static/
–Otherwise: the listener's default pool, or 503 without one

Hostnames are lowercased and internationalised names converted to punycode. A wildcard is refused on HTTPS, where no certificate could cover it.

Certificates and DNS

Every hostname in the rules of an HTTPS listener gets its own Let's Encrypt certificate, renewed 30 days before it expires. It is requested once the name points to the load balancer: create an A record to its ipv4 and an AAAA to its ipv6. Until then the certificate shows dns_pending in certificates; a failure shows failed with the reason, and is retried an hour later.

Who can connect

Only ports 80, 443 and your listeners' ports are open on the load balancer's address. Each listener accepts sources, a list of IPv4/IPv6 addresses or ranges, to restrict who may connect (for a database, an office or a CDN); null lets everyone in. While an HTTPS listener exists, port 80 stays open to everyone: Let's Encrypt validates certificates there.

bash
curl -s -X PATCH https://api.ffxf.net/v1/load-balancers/4/listeners/16 \
     -H "Authorization: Bearer $FFXF_TOKEN" -H "Content-Type: application/json" \
     -d '{"sources": ["203.0.113.0/24", "2001:db8::/32"]}'

Day to day

ActionCallGood to know
See healthGET /load-balancers/{id}Each target shows health, current sessions and response_ms. config_applied turns true once your last change is live, within about 10 seconds.
Drain a targetPATCH …/pools/{pool}/targets/{target} with {"drain": true}No new connections; current ones finish. Do it before maintenance.
StatisticsGET /load-balancers/{id}/metrics?range=24hRequests by response class, connections, bytes, peak sessions; 1h, 24h or 7d, kept 7 days.
DeleteDELETE /load-balancers/{id}The address and configuration go away and billing stops; the target machines are not touched.

Limits and billing

Three load balancers per account by default; per load balancer, 10 pools, 25 targets per pool, 5 listeners, 25 rules per listener and 15 HTTPS hostnames. A load balancer is billed by the hour. Its traffic is counted on the target machines, as if they had served it themselves, so it uses their included bandwidth.

Useful details

Reading needs vms.read; creating needs vms.create and an Idempotency-Key; deleting needs vms.destroy; pools, targets, listeners and rules need network.write. The MCP server exposes the same actions: see MCP tools.

Support & discussions

Technical questions, incident reports, or infrastructure discussions, the team is reachable on Discord, Telegram, X, Instagram, Reddit, and IRC.