Routing
Learn how Octopus routes incoming requests to upstream services.
Overview01
Octopus uses a trie-based router for efficient path matching. Routes are defined in configuration and can be dynamically updated through FARP, the Kubernetes operator, or the admin API.
This page explains routing ideas (path matching, parameters, priority, prefix
rewriting). Some examples below show fields and routing modes that are not
part of the current configuration schema (for example match_type,
conditions, route_groups, route-level retries, and
rate_limit.requests_per_second). For the source-verified routes[] schema —
path, methods, upstream, priority, strip_prefix, add_prefix,
auth_provider/skip_auth/require_roles/require_scopes/authz_rule,
timeout, rate_limit (requests_per_window + window_size), and cors —
always defer to Routes. Note rate_limit and
cors are stored but not enforced in the live chain today (see
Middleware).
Basic Routing02
Simple Path Match
routes:
- path: /api/users
upstream: user-service
methods: [GET, POST]Matches:
GET /api/users✅POST /api/users✅PUT /api/users❌ (method not allowed)GET /api/users/123❌ (path doesn't match)
Wildcard Matching
routes:
- path: /api/users/*
upstream: user-service
methods: [GET, POST, PUT, DELETE]Matches:
/api/users/123✅/api/users/123/posts✅/api/users/123/posts/456✅/api/users❌ (no wildcard match)
Path Parameters
routes:
- path: /api/users/:id
upstream: user-service
methods: [GET, PUT, DELETE]
- path: /api/users/:id/posts/:post_id
upstream: user-service
methods: [GET]Matches:
/api/users/123→id=123✅/api/users/456/posts/789→id=456, post_id=789✅
Path parameters are available in middleware and can be forwarded to upstreams.
Routing Strategies03
Exact Match
routes:
- path: /health
upstream: health-service
match_type: exactOnly matches /health exactly.
Prefix Match
routes:
- path: /api/
upstream: api-service
match_type: prefixMatches any path starting with /api/.
Regex Match
routes:
- path: /api/v[0-9]+/users
upstream: user-service
match_type: regexMatches /api/v1/users, /api/v2/users, etc.
Regex routing is slower than trie-based matching. Use sparingly.
Route Priority04
When multiple routes match, priority determines which one is used:
routes:
# Highest priority (exact match)
- path: /api/users/me
upstream: auth-service
priority: 100
# Medium priority (path parameter)
- path: /api/users/:id
upstream: user-service
priority: 50
# Lowest priority (wildcard)
- path: /api/*
upstream: default-service
priority: 10Request to /api/users/me:
Matches all three routes
Routes to
auth-service(highest priority)
Default Priority
Exact matches: 100
Path parameters: 50
Wildcards: 10
Custom: Any value you specify
Method Routing05
Specific Methods
routes:
- path: /api/users
upstream: user-service
methods: [GET, POST]Method-Specific Configuration
routes:
- path: /api/users
upstream: user-service
methods:
- method: GET
timeout: 10s
- method: POST
timeout: 30s
rate_limit:
requests_per_second: 10HEAD and OPTIONS
routes:
- path: /api/users
upstream: user-service
methods: [GET, POST, PUT, DELETE]
auto_head: true # Auto-handle HEAD requests
auto_options: true # Auto-handle OPTIONS (CORS)Host-Based Routing06
Route based on the Host header:
routes:
- host: api.example.com
path: /*
upstream: api-v1
- host: api-v2.example.com
path: /*
upstream: api-v2
- host: "*.staging.example.com"
path: /*
upstream: staging-apiHeader-Based Routing07
Route based on request headers:
routes:
- path: /api/*
upstream: api-v2
conditions:
- header: X-API-Version
value: v2
- path: /api/*
upstream: api-v1 # DefaultMultiple Conditions
routes:
- path: /api/*
upstream: beta-api
conditions:
- header: X-Beta-User
value: "true"
- header: X-API-Key
exists: trueAll conditions must match.
Query Parameter Routing08
routes:
- path: /api/search
upstream: search-v2
conditions:
- query: version
value: v2
- path: /api/search
upstream: search-v1Path Manipulation09
Octopus rewrites the path before proxying using two fields: strip_prefix
(removed from the front of the path) and add_prefix (prepended). When both are
set, the prefix is stripped first and then the new prefix is added. This is the
prefix rewriting applied in handler.rs for HTTP, WebSocket, SSE, and gRPC.
Strip Prefix
routes:
- path: /api/v1/*
upstream: user-service
strip_prefix: /api/v1 # Forward without the prefixRequest: /api/v1/users/123
Forwarded: /users/123
Add Prefix
routes:
- path: /*
upstream: service
add_prefix: /v2Request: /users/123
Forwarded: /v2/users/123
There is no regex-capture rewrite field. Path rewriting is limited to
strip_prefix and add_prefix. See Routes.
Timeout Configuration10
routes:
- path: /api/users
upstream: user-service
timeout: 30s # Total request timeout
connect_timeout: 5s # Connection timeout
read_timeout: 20s # Read timeoutRetries11
Routes have no retries/retry_on fields. Retry behavior lives in the
proxy layer (proxy.proxy_with_retry), and load balancing, health checks, and
circuit breaking are configured per upstream, not per route. See
Upstreams.
Load Balancing12
Load-balancing policy is set on the upstream via lb_policy, not on the
route:
upstreams:
- name: api-service
lb_policy: least_connections
instances:
- id: api-1
host: 10.0.0.11
port: 8080See Load Balancing and Upstreams for details.
Circuit Breaker13
Circuit breakers are configured per upstream, not per route:
upstreams:
- name: order-service
circuit_breaker:
error_threshold: 50.0
min_requests: 20
timeout: 30s
instances:
- id: order-1
host: 10.0.0.21
port: 8080See Circuit Breaker for details.
WebSocket Routing14
routes:
- path: /ws
upstream: websocket-service
protocol: websocket
timeout: 3600s # Long timeout for WS connectionsgRPC Routing15
routes:
- path: /grpc.*
upstream: grpc-service
protocol: grpc
grpc:
transcoding: true # Enable HTTP→gRPC transcodingRoute Metadata16
Attach metadata to routes for logging/metrics:
routes:
- path: /api/users
upstream: user-service
metadata:
team: identity
version: v2
cost_center: eng-001Dynamic Routes17
Routes can be added/removed dynamically:
Via Admin API
# Add route
curl -X POST http://localhost:9090/_/routes \
-H "Content-Type: application/json" \
-d '{
"path": "/api/new",
"upstream": "new-service",
"methods": ["GET"]
}'
# Remove route
curl -X DELETE http://localhost:9090/_/routes/api-newVia FARP
FARP automatically creates routes from service manifests:
{
"service_name": "user-service",
"schemas": [{
"type": "openapi",
"location": { "url": "http://user-service/openapi.json" }
}]
}See FARP Protocol for details.
Route Groups18
Organize routes with common configuration:
route_groups:
- name: api-v1
prefix: /api/v1
middleware: [auth, rate_limit]
timeout: 30s
routes:
- path: /users
upstream: user-service
- path: /orders
upstream: order-service
- name: api-v2
prefix: /api/v2
middleware: [auth, rate_limit, compression]
timeout: 60s
routes:
- path: /users
upstream: user-service-v2
- path: /orders
upstream: order-service-v2Internal Routes19
Routes handled by the gateway itself:
routes:
- path: /_/health
internal: true
handler: health_check
- path: /_/metrics
internal: true
handler: metrics
- path: /_/config
internal: true
handler: config
auth_required: trueRoute Validation20
Validate routes on startup:
octopus validate --config config.yamlChecks:
No duplicate paths with same priority
All upstreams exist
Valid path patterns
Valid method names
Valid condition syntax
Performance21
Lookup Time
Exact match: O(k) where k is path length
Path parameters: O(k * p) where p is number of parameters
Wildcard: O(k * n) where n is number of wildcards
Regex: O(n) where n is number of regex routes
Memory Usage
Per route: ~128 bytes
Trie node: ~64 bytes
Path parameter: ~32 bytes
Optimization Tips
Use exact matches when possible
Limit regex routing
Order routes by frequency (most common first)
Use route groups for common configuration
Avoid deep path nesting
Examples22
RESTful API
routes:
# List users
- path: /api/users
upstream: user-service
methods: [GET]
# Create user
- path: /api/users
upstream: user-service
methods: [POST]
rate_limit:
requests_per_second: 10
# Get/update/delete user
- path: /api/users/:id
upstream: user-service
methods: [GET, PUT, DELETE]Microservices
routes:
# User service
- path: /users/*
upstream: user-service
# Order service
- path: /orders/*
upstream: order-service
# Product service
- path: /products/*
upstream: product-service
# Payment service (with circuit breaker)
- path: /payments/*
upstream: payment-service
circuit_breaker:
enabled: true
failure_threshold: 3API Versioning
routes:
# v1 API
- path: /api/v1/*
upstream: api-v1
timeout: 30s
# v2 API
- path: /api/v2/*
upstream: api-v2
timeout: 60s
middleware: [auth, rate_limit, compression]
# Default to latest
- path: /api/*
upstream: api-v2Next Steps23
Middleware - Process requests
Load Balancing - Distribute traffic
Health Checks - Monitor upstreams
FARP Protocol - Auto-generate routes
Routes configuration - The real route schema