FARP Protocol
FARP (Forge API Gateway Registration Protocol) enables automatic service discovery and route generation.
Overview01
FARP eliminates manual route configuration by:
Services register with a
SchemaManifestOctopus watches for manifest changes
Gateway fetches schemas and generates routes
Auto-generates federated API documentation
Zero-downtime updates on schema changes
Enabling FARP02
Discovery backends are configured under farp.discovery.backends. For example, a
Kubernetes backend:
farp:
enabled: true
discovery:
backends:
- type: kubernetes
enabled: true
config:
namespace: "" # "" = all namespaces (cluster-scoped RBAC)
label_selector: "app.kubernetes.io/part-of=myapp"
watch_interval: 30sSee FARP configuration for the full schema and Discovery backends for the supported backends (mDNS, Consul, DNS, Kubernetes).
Service Manifest03
Services expose a manifest describing their APIs:
{
"version": "1.0.0",
"service_name": "user-service",
"service_version": "v1.2.3",
"schemas": [
{
"type": "openapi",
"spec_version": "3.1.0",
"location": {
"type": "http",
"url": "http://user-service:8080/openapi.json"
}
}
],
"capabilities": ["rest", "websocket"],
"endpoints": {
"health": "/health",
"metrics": "/metrics"
}
}Supported Schema Types04
OpenAPI
{
"type": "openapi",
"spec_version": "3.1.0",
"location": {
"type": "http",
"url": "http://service/openapi.json"
}
}Routes are generated from OpenAPI paths.
AsyncAPI
{
"type": "asyncapi",
"spec_version": "2.6.0",
"location": {
"type": "http",
"url": "http://service/asyncapi.json"
}
}WebSocket routes generated from AsyncAPI channels.
gRPC Reflection
{
"type": "grpc",
"location": {
"type": "grpc_reflection",
"address": "service:50051"
}
}gRPC routes from service reflection.
Discovery Backends05
FARP can source instances from several backends, each configured under
farp.discovery.backends: Kubernetes (EndpointSlice-based Pod discovery),
Consul, DNS, and mDNS/Bonjour (zero-config, for local development).
An etcd discovery backend exists in the source tree but is not selectable from the gateway configuration today. See Discovery backends for the source-verified breakdown and Kubernetes discovery for in-cluster setup.
Route Generation06
FARP generates routes from schemas:
# From OpenAPI
GET /api/users -> user-service
POST /api/users -> user-service
GET /api/users/{id} -> user-service
# From AsyncAPI
WS /ws/chat -> chat-service
# From gRPC
POST /grpc/user.UserService/GetUser -> user-serviceFARP API Endpoints07
All FARP endpoints are mounted under /__/farp/ prefix:
Federated Schemas
# Access federated OpenAPI
curl http://gateway:3000/__/farp/openapi.json
# Access federated AsyncAPI
curl http://gateway:3000/__/farp/asyncapi.json
# Access federated GraphQL schema
curl http://gateway:3000/__/farp/graphql
# Access federated gRPC schema
curl http://gateway:3000/__/farp/grpcService Management
# List all registered services
curl http://gateway:3000/__/farp/services
# Get specific service details
curl http://gateway:3000/__/farp/services/user-service
# Register a service
curl -X POST http://gateway:3000/__/farp/register \
-H "Content-Type: application/json" \
-d @manifest.json
# Update a service
curl -X PUT http://gateway:3000/__/farp/services/user-service \
-H "Content-Type: application/json" \
-d @manifest.json
# Deregister a service
curl -X DELETE http://gateway:3000/__/farp/services/user-serviceSchema Federation
# List all federated schemas
curl http://gateway:3000/__/farp/schemas
# Get specific schema format
curl http://gateway:3000/__/farp/schema/openapi
curl http://gateway:3000/__/farp/schema/asyncapi
# Trigger manual federation (re-merge all schemas)
curl -X POST http://gateway:3000/__/farp/federateDocumentation UIs
# View in Swagger UI
open http://gateway:3000/__/farp/docs
# View in ReDoc
open http://gateway:3000/__/farp/redocSchema Caching08
farp:
schema_cache_ttl: 5m
schema_max_size: 10MB
checksum_validation: trueSchemas are cached with checksums for change detection.
Hot Reload09
When schemas change:
FARP detects change
Fetches new schema
Regenerates routes
Updates router (zero-downtime)
Route updates happen without dropping existing connections.
Example: Go Service10
// Expose manifest
func FARPManifest() *farp.Manifest {
return &farp.Manifest{
Version: "1.0.0",
ServiceName: "user-service",
ServiceVersion: "v1.0.0",
Schemas: []farp.Schema{
{
Type: "openapi",
Location: farp.HTTPLocation{
URL: "http://user-service/openapi.json",
},
},
},
}
}
// HTTP handler
http.HandleFunc("/.well-known/farp-manifest.json",
func(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(FARPManifest())
})Monitoring11
Service Status
# View all discovered services
curl http://gateway:3000/__/farp/services
# Get detailed service info
curl http://gateway:3000/__/farp/services/user-service | jq .Prometheus Metrics
FARP exposes the following metrics:
# Number of registered services
octopus_farp_services_total
# Number of routes generated per service
octopus_farp_routes_total{service="user-service",type="http"}
# Schema fetch operations
octopus_farp_schema_fetches_total{service="user-service",type="openapi",status="success"}
# Schema fetch duration
octopus_farp_schema_fetch_duration_seconds{service="user-service",type="openapi"}
# Schema updates
octopus_farp_updates_total{service="user-service"}
# Schema cache hit ratio
octopus_farp_cache_hit_ratio
# Parse errors
octopus_farp_parse_errors_total{service="user-service",type="openapi"}Next Steps12
Service Discovery concept - The discovery model
FARP configuration - Configure discovery and caching
Schema federation - OpenAPI/AsyncAPI/GraphQL merging
gRPC Support - gRPC services