HTTP Load Balancer Routes on F5 Distributed Cloud

Route misconfiguration is one of the most common configuration mistakes we see that can cause incidents on F5 Distributed Cloud (F5 XC). The four route types look deceptively simple in the console, but they have distinct behaviors, ordering rules, and gotchas. This article covers all four types with real field names, decision guidance, and the mistakes that actually happen in production.

What Routes Do in F5 XC HTTP Load Balancer

An HTTP Load Balancer in F5 XC is a full L7 proxy running at the Regional Edge (RE) and depending on the deployment model, Customer Edge (CE).  We will use the Regional Edge as a deployment model for this article.

When a request arrives, the RE evaluates the route list in order and applies the first matching route. That route determines what happens to the request: forward it to an origin, redirect the client, return a synthetic response, or apply advanced routing logic.

Routes can be configured inside the HTTP Load Balancer configuration which opens a new Route Options window:

Multi-Cloud App Connect > Load Balancers > HTTP Load Balancers > [your LB] > Routes > Route Options

The four route types map to three underlying route actions:

XC Route Type Route Action Traffic Goes To
Simple Route route Origin Pool
Redirect Route redirect Client (3xx response)
Direct Response Route direct_response Client (fixed response body)
Custom Route route / redirect / direct_response Depends on configuration

Route Matching: How XC Evaluates Routes

Route evaluation is sequential, stops on first match, and has no automatic specificity ranking. The order you set is the order XC uses.

Evaluation Order

The HTTP Load Balancer evaluates routes sequentially, top to bottom. The first route that matches the incoming request wins. No further routes are evaluated.

This means:

  • More specific routes must appear before broader ones.
  • A catch-all route (prefix /) at the top will swallow everything. Nothing below it will ever match.

Path Match Types

Three path match types are available across all route types:

Match Type Field Behavior
Prefix path_prefix Path must begin with the specified string
Exact exact Path must equal the value exactly (query string excluded)
Regex regex Entire path (minus query string) must match the regex pattern

Prefix matching pitfall: The prefix /api matches /api/v1/users but also /apikeys and /api-internal. If you want to match a path segment boundary, use /api/ (trailing slash) or switch to regex.

Additional Matching Criteria

Beyond path, routes can match on:

  • HTTP methods: GET, POST, PUT, DELETE, etc.
  • Request headers: presence, exact value, regex
  • Query parameters: Retain, Remove, or Replace

Combining criteria (e.g., path prefix + method + header) creates an AND condition: all specified criteria must match.

Route Type 1: Simple Routes

Simple routes are the workhorse of most HTTP Load Balancer configurations. They match a path (and optionally method/headers) and forward traffic to an Origin Pool.

When to Use

  • Standard application traffic forwarding
  • Path-based routing to different backend services
  • API versioning (/v1/ → pool A, /v2/ → pool B)
  • Microservice fanout from a single domain

Key Configuration Fields

Field Description
Path match type Prefix / Exact / Regex
HTTP Method Any, GET, POST, PUT, etc…
Origin Pool The backend pool receiving the request
Host Rewrite Method Disable/ Hostname / Header value: rewrites the Host header sent to origin
Query Parameters Retain, Remove, Replace

Advanced Options Worth Knowing

Path rewriting (under Advanced Options):

  • Disabled: path sent to origin unchanged
  • Prefix Replacement: replaces the matched prefix with a new string (e.g., strip /api/v1 prefix before sending to origin)
  • Regex-based: full regex substitution on the path

Retry policy: The default retry policy is 1 retry on 5xx responses. Set this explicitly for your application in every route:

  • Disabled: no retries; required for write operations
  • Default: 1 retry on 5xx
  • Custom: specify retry conditions, count, and interval

Per-route WAF override: Each simple route can attach its own WAF App Firewall policy. This completely replaces the load balancer-level WAF for matching requests; it is not additive. Use this to enforce stricter rules on sensitive paths (e.g., /admin/) or to relax inspection on certain paths.

Example: API Path Routing

Route 1: Prefix /api/v2/ → origin-pool-v2 (exact origin for v2) Route 2: Prefix /api/v1/ → origin-pool-v1 (legacy backend) Route 3: Prefix /api/ → origin-pool-api (catch-all for API paths) Route 4: Prefix / → origin-pool-web (catch-all for everything else)

Order matters here. If route 3 or 4 appeared first, routes 1 and 2 would never fire.

Route Type 2: Redirect Routes

Redirect routes return an HTTP 3xx response directly to the client. No origin pool is involved: the RE handles the response entirely.

When to Use

  • HTTP → HTTPS redirect (though XC has a dedicated LB-level toggle for this)
  • Domain canonicalization (www.example.com → example.com)
  • Legacy URL migrations (/old-path/ → /new-path/)
  • Temporary redirects during maintenance or A/B migrations

Key Configuration Fields

Field Description
Protocol HTTP or HTTPS
Host Target FQDN; supports non-standard ports
Redirect Path / URI Target path; if left unset, original URI is preserved (including query string)
Response Code 301 (Permanent), 302 (Temporary), 307, 308

Redirect Behavior: URI Preservation

When you leave the redirect path unset, XC preserves the original URI path and query string in the Location header. This is useful for protocol/host-only redirects where you just want to change the scheme or domain without touching the path.

Example: Redirect all HTTP traffic to HTTPS on the same host:

Protocol: HTTPS Host: same-as-request (leave blank or match domain) Path: (unset — preserve original URI) Code: 301

Redirect Route Limitations

Simple redirect routes (defined directly on the LB) do not support custom header manipulation on the redirect response. If you need to inject headers (e.g., Cache-Control: no-store on the redirect response), use a Custom Route object instead.

Route Type 3: Direct Response Routes

Direct response routes return a fully synthetic HTTP response to the client. The request never reaches an origin pool: the RE generates the response itself.

When to Use

  • Health check endpoints that should always return 200 (e.g., /healthz) without touching the app
  • Maintenance mode pages: serve a 503 with a message body while origin is down
  • Blocking specific paths with a meaningful error body (vs. a generic deny)
  • Canary or feature-flag placeholders that return 404 before the feature ships
  • Robots.txt or security.txt served from the edge without an origin

Key Configuration Fields

Field Description
HTTP Status Code Any valid HTTP status code (200, 403, 503, etc.)
Response Body Static text or HTML body returned to client
Path match Same prefix/exact/regex options as other route types

Example: Edge-Served Health Check

Path: Exact /healthz Method: GET Action: Direct Response Status: 200 Body: OK

This responds to health probes from AWS ALB, Kubernetes ingress controllers, or uptime monitors without any load on the backend. Particularly useful during blue/green deployments when the app might not yet be healthy.

Route Type 4: Custom Routes

Custom routes reference standalone Route objects created separately in XC and attached to one or more HTTP Load Balancers. Unlike the other three types, they follow a service-mesh model rather than a traditional LB model.

When to Use Custom Routes

  • Weighted traffic splitting between origin pools (canary releases, blue/green)
  • Request/response header manipulation not available on simple routes
  • Advanced retry policies with specific conditions and intervals
  • Traffic mirroring (shadow traffic to a secondary backend for testing)
  • Reusable route logic shared across multiple load balancers

Architecture: Route Objects vs. Inline Routes

Inline routes (simple, redirect, direct response) are defined directly on the HTTP Load Balancer. Custom route objects are:

  1. Created as standalone objects under Multi-Cloud App Connect
  2. Referenced by the HTTP Load Balancer
  3. Reusable: multiple LBs can reference the same route object

Weighted Clusters

Custom routes enable weighted traffic splitting across multiple upstream clusters, equivalent to BIG-IP pool ratio weights or AWS ALB weighted target groups.

Route: Prefix /api/ Cluster A (origin-pool-v2): weight 90 Cluster B (origin-pool-v1): weight 10

This is the correct mechanism for canary deployments and gradual traffic shifts on F5 XC. The weights are percentage-based and must sum to 100.

Header Manipulation

Custom routes support header operations at the route level, applied before forwarding to origin:

Operation Direction Example
Add header Request X-Forwarded-For: {client-ip}
Remove header Request Strip Authorization before certain paths
Add header Response Strict-Transport-Security: max-age=31536000
Remove header Response Strip Server header from responses

Header manipulation runs in order: route-level → virtual host-level → route configuration-level.

Retry Policies

Route retry policies take complete precedence over any virtual host-level retry policy. Configure explicitly:

Field Description
Retry on Conditions: 5xx, gateway-error, reset, connect-failure, retriable-4xx
Number of retries Integer
Per-try timeout Timeout applied to each individual retry attempt
Retry interval Base interval between retries

Traffic Mirroring

Mirror policies shadow a copy of each request to a secondary cluster. The mirrored request is fire-and-forget.  Example:

  • Testing a new backend version against live traffic without affecting users
  • Security analysis pipelines

Route Ordering and Priority

Route order is the most common source of routing bugs in XC deployments. There is no automatic specificity ranking; you own the order.

The Rules

  1. Routes evaluate top to bottom.
  2. First match wins. Evaluation stops.
  3. Disabling a route (via the Route Activation Status toggle) does not remove it: traffic falls through to the next matching route.

Recommended Ordering Pattern

Order routes from most specific to least specific:

  1. Exact paths first Exact /api/v2/auth/token 2. Specific prefixes next Prefix /api/v2/ 3. Broader prefixes after Prefix /api/ 4. Path-specific exceptions Exact /healthz 5. Catch-all last Prefix /

Common Ordering Mistakes

Mistake Symptom Fix
Catch-all prefix / first All traffic hits one origin; other routes never fire Move catch-all to last position
/api prefix before /api/v2/ V2 traffic hits wrong origin Reverse the order
Disabled/Unused route above active route Traffic silently hits next route with different behavior Remove disabled routes; don’t rely on toggle for permanent changes
Redirect route below a prefix match Redirect never fires Move redirect above the prefix that would match it first

Common Mistakes and Gotchas

Prefix /api matches /apikeys. The prefix match does not anchor to path segment boundaries. /api matches /api/, /api/v1/, and also /apikeys, /api-docs. Use /api/ (trailing slash) or regex if segment boundary matters.

Per-route WAF is a full replacement, not additive. Attaching a WAF policy to a route does not stack with the LB-level WAF. It replaces it entirely for that route. If your LB WAF is in blocking mode and you attach a route-level WAF in monitoring mode, that route is now in monitoring mode only.

Custom routes enforce TLS: test before production. If your origin uses a self-signed certificate and you switch from a simple route to a custom route without uploading the Root CA, connections will fail. Test in a staging environment first.

Header manipulation on redirect requires a custom route object. Simple redirect routes in XC do not support response header injection. If you need Cache-Control or Vary headers on your redirects, you must use a standalone custom route object with redirect action.

Regex route performance at scale. Regex routes require full path evaluation on every request. At high request volumes, a large number of regex routes adds measurable CPU overhead compared to prefix or exact routes. Use regex only where prefix or exact matching is insufficient.

FAQ

Q: What is the difference between a Simple Route and a Custom Route?

A: Simple routes are inline on the HTTP Load Balancer and forward traffic directly to an Origin Pool. Custom routes are standalone objects that use an Endpoints → Clusters → Routes model, support weighted traffic splits, header manipulation, and mirroring, but cannot reference Origin Pools directly.

Q: Why is my catch-all route matching everything instead of the specific routes below it?

A: Route evaluation stops at the first match. If your catch-all prefix (/) is above more specific routes, it wins every time. Move the catch-all to the last position in the list.

Q: Can I use a Custom Route to send traffic directly to an F5 XC Origin Pool?

A: No. Custom routes do not support Origin Pools directly. They use an Endpoints → Clusters → Routes abstraction. If you need weighted splitting with Origin Pool support, custom routes are not the right fit; simple routes forward to Origin Pools but do not support weighted clusters.

Q: My POST requests are creating duplicate records and I traced it to XC retries. What is happening?

A: The default retry policy on simple routes is “1 retry on 5xx.” A POST that hits a 500 gets retried once, potentially double-writing. Set the retry policy to Disabled on any route handling non-idempotent operations (POST, PUT, PATCH, DELETE).

Q: Does attaching a WAF policy to a route add rules on top of my LB-level WAF?

A: No. Per-route WAF replaces the LB-level WAF entirely for requests matching that route. If your LB WAF is in blocking mode and the route WAF is in monitoring mode, those requests are evaluated in monitoring mode only.

Q: My Custom Route TLS connections to origin are failing but the same origin works fine on a Simple Route. Why?

A: Custom routes enforce strict TLS with no skip-verify option. Simple routes do not have this requirement. For custom routes, upload the Root CA certificate for your origin, or use the use_volterra_trusted_ca_url flag via the API for public CAs. Self-signed certs without the Root CA uploaded will fail silently.

Q: I disabled a route in the console but traffic behavior changed unexpectedly. What happened?

A: Disabling a route via the Route Activation toggle does not remove it from evaluation. Traffic falls through to the next matching route in the list. If that route is a broad catch-all, the behavior shift may look correct until something that depends on specific routing breaks. Remove routes you no longer need rather than toggling them off.

3 Likes

I disabled a route in the console but traffic behavior changed unexpectedly. What happened?

I haven’t run into this issue, myself, but this is certainly an interesting behavior. Am I correct in saying it behaves like a switch/case wherein the case body is, instead of the typical “what to do with this route” logic, replaced with a `continue` ?

What’s the behavior if there is simply no matching route that follows (ie, no catch-all)? Will the traffic follow the load balancer’s default pools?

Hey Tyler, Yes as long as the HTTP-LB has a default origin pool this will be a catch-all or fallback pool.  If no default origin is configured then the client should get a HTTP-404

That’s very interesting. Have you observed that behavior? I was of the impression that the default origin pool settings were ignored once a route was introduced, regardless of matching (thus requiring a ‘catch all route’ to exist, where you set what should be your default origin pool settings).

Unfortunately I don’t have a place to safely test this.

Yes I was able to validate.  If you set an origin pool on the HTTP-LB and then add a route to the HTTP-LB the origin pool goes to the bottom of the ordered list.  If you do not set a origin pool and there is no route match the client gets a HTTP 404