Octopus
1.x
Docs/Octopus/Schema federation
Open

Reading5 min
Updated31 Jul 2026
Sourcev1/farp/schema-federation.mdx

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:

  1. Generates routes so the gateway can proxy requests to the service.

  2. 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

Warning

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:

FormatAuto-discovery routesPush-registration routesFederation (merge into unified surface)
OpenAPIYes — paths × methods become routesYesYes — true structural merge of paths/components
AsyncAPINoYes — channels become GET /ws{channel} routesYes — structural merge of channels
GraphQLNoYes — POST/GET /graphql endpoint routesConcatenation only (schemas are joined as text, not stitched)
gRPCNoNo — returns an "unsupported format" errorConcatenation only (no real proto merge)
CustomNoNoConcatenation only
Note

"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 service orders becomes a route at /orders/users/{id}.

  • The service prefix (/orders) is stripped, so the upstream still sees /users/{id}.

  • Routes are registered at priority 100 and 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.

Note

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:

EndpointServes
GET /farp/openapi.jsonMerged OpenAPI spec (also at /openapi.json).
GET /farp/asyncapi.jsonMerged AsyncAPI spec (also at /asyncapi.json).
GET /farp/graphqlCombined GraphQL schemas (also at /graphql).
GET /farp/grpcCombined gRPC/proto schemas (also at /grpc).
GET /farp/schemasLists the federated formats currently available.
GET /farp/docsSwagger UI over the merged OpenAPI spec.
GET /farp/redocRedoc UI over the merged OpenAPI spec.
Note

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:

1

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.

Note

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.

Where to go next06