How Versus models F5 BIG-IP load-balancing pools, their address:port members, and the health monitors that gate them — a read-only mirror of the device, with per-member status and stats, monitor cross-references, and a REST API for each.
A pool is the set of back-end servers a virtual server load-balances across; its members are the individual address:port targets; and health monitors are the probes that decide, member by member, whether a target is fit to receive traffic. Versus discovers all three from your F5 BIG-IP devices and keeps them as first-class objects in inventory, cross-linked to the virtual servers that use them.
This page covers how those objects are modeled, how they stay in sync with the device, and the REST API for reading and operating on them. For the device connection itself, see F5 BIG-IP Integration.
Versus stores three related objects, all scoped to the device they were discovered on:
| Object | What it is | Keyed by |
|---|---|---|
| Pool | A load-balancing group with a method and a health state | device + partition + name |
| Pool Member | One address:port target inside a pool | pool + name |
| Monitor | A health probe that can be attached to pools | device + partition + name |
Everything carries the F5 partition it lives in (defaulting to Common), so /Common/web_pool and /Tenant-A/web_pool are distinct objects even on the same box.
A pool records its load-balancing method, a rolled-up availability state, and its relationships to virtual servers and monitors:
lb_method — mirrors the F5 load-balancing-mode verbatim (e.g. round-robin), so what Versus shows is what the device is actually configured to do.status, members_available, members_total — the pool's health at a glance: how many members are up out of the total.virtual_servers — a many-to-many link to every virtual server that references this pool. This is a real stored relation, resolved at import time (a VS can name a pool directly, or reach it indirectly through an iRule or LTM policy).monitors — a many-to-many link to the health monitors assigned to the pool. A pool can carry more than one; when it does, the generated TMSH renders it as a monitor min 1 of { … } rule.raw_config — the pool's description, allowNat, and allowSnat settings, kept as-is.Each member is a single target within one pool:
| Field | Meaning |
|---|---|
name | The member's F5 name, typically address:port |
address | The member IP |
port | The service port |
status | up, down, unknown, disabled, or forced_offline |
enabled | Whether the member is administratively enabled |
connections, bits_in, bits_out, requests | Traffic counters from the device |
last_updated | When Versus last refreshed this member |
The status field distinguishes a member that is genuinely down (failing its monitor) from one an operator has taken out of rotation — disabled (session user-disabled) or forced_offline. That distinction is what lets a dashboard show "2 of 3 up, 1 disabled for maintenance" rather than a false alarm.
A monitor is a reusable probe definition:
| Field | Meaning |
|---|---|
monitor_type | http, https, tcp, tcp-half-open, icmp, gateway-icmp, udp, external, or other |
interval | Seconds between probes (default 5) |
timeout | Seconds before a probe is considered failed (default 16) |
send_string | The request string sent (e.g. an HTTP GET) |
recv_string | The expected response substring |
Monitors are defined once per device and attached to any number of pools. Versus tracks that attachment through the pool's monitors relation, so from a monitor you can see exactly which pools depend on it (see Monitor cross-references below).
Alongside pools, Versus also imports Nodes — the device-level definition of a back-end host (address, ratio, optional node-level monitor, enabled state). On F5, pool members reference nodes by address, so Versus resolves a node's "referenced by" list by matching pool members on the same device that share its address. Nodes are read-only in Versus and live at GET /api/nodes/.
Pools, members, and monitors are a read-only mirror of the device — Versus does not invent them, it reflects them. They are populated by the F5 import that runs when you discover or re-sync a BIG-IP, and the import is authoritative:
device + partition + name for pools and monitors, pool + name for members) and updated in place if it already exists, so IDs and history are stable across syncs.enabled is derived from the F5 session state (session user-disabled → disabled), and member status is mapped from the device's reported availability.Because the source of truth is the device, changes you want to make to pools and members flow the other way — through change-controlled workflows and generated infrastructure-as-code (Ansible / AS3 / TMSH per virtual server), not by editing the mirror. The generated TMSH for a virtual server includes its pools, members, and monitor rules, built live from this synced snapshot.
Like the rest of the platform, these objects are tenant-isolated: in multi-tenant deployments the pool and member APIs enforce row-level separation in the data layer, on top of application permission checks. See Platform Architecture.
All endpoints are under your Versus base URL, e.g. https://versus.example.com/api/…, and require a JWT bearer token (see Running Workflows via the API for the auth flow).
GET /api/pools/?device={id}
GET /api/pools/{id}/
A pool serializes with its members inline, its monitors (monitors_detail), the virtual servers it serves (virtual_servers_detail), and the owning device_name. Filter by device or by virtual_servers, and search by name.
To find everything that points at a pool — not just the virtual servers that name it directly, but the iRules and LTM policies that select it in their logic — call:
GET /api/pools/{id}/references/
This re-derives the same reference resolution F5 itself performs at config-apply time (scanning each linked VS's iRule and policy definitions for this pool's path) and returns the matching virtual servers, iRules, and LTM policies. It reads only already-synced data — no live device call.
GET /api/pool-members/?pool={id}&status=up&enabled=true
GET /api/pool-members/{id}/stats_history/?hours=24
POST /api/pool-members/{id}/toggle/
List and filter members by pool, status, or enabled. The stats_history action returns time-series traffic (cur_conns, bits_in, bits_out, requests) for the member over the requested window, from Versus's periodic stats collection. The toggle action flips the stored enabled flag on the member record.
GET /api/monitors/?device={id}&monitor_type=https
Monitors are read-only. Each entry includes its device_name, whether it is a built-in F5 system monitor (is_builtin), and its referenced_by list. Filter by device, partition, or monitor_type.
Because the pool-to-monitor link is a real stored relation, a monitor's referenced_by is exact — it lists the pools using it directly, with no heuristics:
"referenced_by": [
{ "type": "pool", "id": 41, "name": "Common/web_pool", "url": "/applications/pools/41" }
]
The is_builtin flag lets the UI separate the monitors you care about from F5's shipped defaults (http, tcp, gateway_icmp, and the rest), so a "delete unused monitors" review doesn't flag system objects.
To pull fresh pool and member health directly from the device — bypassing the last-synced snapshot — use the virtual server's live-stats action:
GET /api/virtual-servers/{id}/live_stats/
This reaches the BIG-IP in real time and returns the VS's connection and throughput counters together with each pool's members and their current cur_conns, bits_in, bits_out, and requests. Use it for an on-demand "is this pool healthy right now?" check; use the stored objects and stats_history for trends and reporting.
A lighter, snapshot-based variant used by the App Builder pool-member editor returns all pools, members, and attached monitors for a VS without a live device call:
GET /api/virtual-servers/{id}/pools-with-members/
Pools, members, and monitors are the load-balancing layer beneath every discovered virtual server. They give you a searchable, reportable inventory of exactly what your F5 estate balances traffic across, which monitors gate it, and which member is down versus deliberately drained — all kept honest by an import that mirrors the device rather than a config you maintain by hand. When you do need to change a pool, that change runs as an auditable workflow, and the credentials it uses come from the Secret Vault or an outbound collector rather than being embedded anywhere.