Schema federation
Once a discovery backend tells FARP where a service lives, FARP fetches that service's published schema and does two things with it:
Generates routes so the gateway can proxy requests to the service.
Federates it into a single, gateway-wide API surface that combines every registered service.
There are two ways a schema reaches FARP, and they support different formats — so it is worth being precise about each.
Two registration paths01
Auto-discovery is the common case, and it generates routes from OpenAPI documents only. If
your services expose AsyncAPI/GraphQL and you want routes generated automatically, use the push
registration API (or supply a v1.1.0 route_table). Don't assume gRPC routes are generated — see
below.
Supported schema formats02
FARP recognises five schema format tags: openapi, asyncapi, grpc, graphql, and custom.
Support differs between route generation and federation:
| Format | Auto-discovery routes | Push-registration routes | Federation (merge into unified surface) |
| OpenAPI | Yes — paths × methods become routes | Yes | Yes — true structural merge of paths/components |
| AsyncAPI | No | Yes — channels become GET /ws{channel} routes | Yes — structural merge of channels |
| GraphQL | No | Yes — POST/GET /graphql endpoint routes | Concatenation only (schemas are joined as text, not stitched) |
| gRPC | No | No — returns an "unsupported format" error | Concatenation only (no real proto merge) |
| Custom | No | No | Concatenation only |
"Concatenation only" means the federation engine joins the source documents into one text blob with per-service comment headers; it does not perform a semantic merge. Only OpenAPI and AsyncAPI go through real structural mergers.
How OpenAPI routes are generated03
For each path in the OpenAPI document, FARP creates one route per HTTP method
(GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS; other keys like parameters are skipped).
Routes are mounted under a service prefix and the prefix is stripped before proxying upstream:
A path
/users/{id}on serviceordersbecomes a route at/orders/users/{id}.The service prefix (
/orders) is stripped, so the upstream still sees/users/{id}.Routes are registered at priority
100and point at an upstream cluster named after the service.
If the service's manifest declares an auth_config (an auth provider, required roles, or required
scopes), those settings are applied to every generated route.
Introspection endpoints are filtered out by default — paths like /, /health, /docs*,
/openapi*, /asyncapi*, and /_farp/* are excluded from both generated routes and the
federated spec. Set FARP_INCLUDE_INTROSPECTION_ENDPOINTS=1 to keep them.
The federated API surface04
As schemas are registered, FARP merges them per format and serves the combined results. The merged
OpenAPI document rewrites its servers array to the gateway root (/) so "Try it out" requests in
the docs UIs hit the gateway rather than the original fetch URL.
The federation engine exposes these endpoints from the FARP API handler:
| Endpoint | Serves |
GET /farp/openapi.json | Merged OpenAPI spec (also at /openapi.json). |
GET /farp/asyncapi.json | Merged AsyncAPI spec (also at /asyncapi.json). |
GET /farp/graphql | Combined GraphQL schemas (also at /graphql). |
GET /farp/grpc | Combined gRPC/proto schemas (also at /grpc). |
GET /farp/schemas | Lists the federated formats currently available. |
GET /farp/docs | Swagger UI over the merged OpenAPI spec. |
GET /farp/redoc | Redoc UI over the merged OpenAPI spec. |
By default, service tags from each source spec are kept so operations stay grouped by service.
Set FARP_COLLAPSE_SERVICE_TAGS=1 (or the per-service
farp.collapse_service_tags = true metadata) to collapse them into a single tag per service.
How changes are reconciled05
FARP keeps the gateway in sync with the live fleet on every watch tick:
New instance appears. Once an instance advertises farp.enabled = true, FARP registers it,
fetches its OpenAPI schema, registers an upstream cluster, and generates routes.
Instance disappears. A missing instance is not removed immediately. FARP counts consecutive
missed discovery cycles and only deregisters the service after a grace period (3 missed cycles by
default — e.g. 15 seconds at a 5s watch_interval). This rides out transient blips.
Schema cache expires. When a registration is older than farp.schema_cache_ttl (default 5m),
the next discovery cycle re-fetches the service's schema, clears the stale schemas, and re-generates
routes.
Routes change (v1.1.0). Manifests can carry a routes_checksum. If the checksum is unchanged
since the last sync, FARP skips route regeneration entirely; when it changes, routes are
re-generated for an atomic swap.
After the first full discovery pass completes, FARP flips a readiness flag so the gateway's
/readyz probe only reports ready once discovery has converged. See
Kubernetes probes & drain.