Auto-discover services with FARP
FARP — the Forge API Gateway Registration Protocol — flips
hand-written routing around: a discovery backend reports live service instances,
Octopus fetches each one's published OpenAPI document, and turns its paths and
methods into routes. As services scale, appear, or disappear, the routes follow.
Static upstreams/routes and FARP discovery coexist, so you can adopt it
incrementally.
Make services advertise themselves01
FARP only registers an instance — and generates routes for it — when its
discovery metadata advertises farp.enabled = true. The OpenAPI document is then
fetched from farp.openapi.path (default /openapi.json). How you set that
metadata depends on the backend:
Kubernetes — carried on the Service/Pod metadata; filter with a
label_selector.Consul — service
Meta.mDNS — TXT records.
Instances without farp.enabled are discovered but skipped. See
what a backend reports.
Enable FARP and pick a backend02
Set farp.enabled: true and list one or more backends under
farp.discovery.backends. Each entry is tagged by type
(mdns | dns | consul | kubernetes), has an enabled flag, and a
backend-specific config.
farp:
enabled: true
watch_interval: 5s
schema_cache_ttl: 5m
discovery:
backends:
- type: kubernetes
enabled: true
config:
namespace: default
label_selector: "app.kubernetes.io/part-of=myapp"
watch_interval: 10s
use_endpoint_slices: true
include_not_ready: falsefarp:
enabled: true
watch_interval: 5s
schema_cache_ttl: 5m
discovery:
backends:
- type: mdns
enabled: true
config:
service_type: _octopus._tcp
domain: local.
watch_interval: 30s
query_timeout: 5s
enable_ipv6: falseEach backend is gated behind a Cargo feature in the gateway build (mdns,
dns, consul, kubernetes); the default runtime build enables only mdns.
A configured-but-not-compiled backend is logged and skipped, not fatal. There
is no type: etcd backend. The DNS backend is experimental (only
watch_interval is applied) — prefer mDNS, Consul, or Kubernetes. See
Discovery backends.
Validate and run03
octopus validate -c gateway.yaml
octopus serve -c gateway.yamlA complete, validated configuration (Kubernetes backend):
gateway:
listen: "0.0.0.0:8080"
farp:
enabled: true
watch_interval: 5s
schema_cache_ttl: 5m
discovery:
backends:
- type: kubernetes
enabled: true
config:
namespace: default
label_selector: "app.kubernetes.io/part-of=myapp"
watch_interval: 10s
use_endpoint_slices: true
include_not_ready: falseWatch routes appear04
On each tick of watch_interval, Octopus polls every enabled backend, fetches
the OpenAPI document of any newly advertised instance, and generates routes from
it. Inspect the live route table through the
admin dashboard (/admin/routes) or the
Admin API. Scale a discovered Deployment up or
down and the routes reconcile to match.
Readiness and discovery05
If you also run on Kubernetes with probes, /readyz can wait for the first
discovery sync before reporting ready — gateway.probes.require_discovery_sync
(default true) keeps a freshly started pod out of the Service EndpointSlice
until it knows where its upstreams are. See Probes & drain
and the observability guide.
See also06
Service Discovery & FARP — the discovery and auto-routing model.
Discovery backends — every backend's fields and honest status.
Schema federation — how published schemas become a unified API surface.